Page tree

This article will help you troubleshoot some of the most common issues encountered with faxes.

Faxes can be sent over audio stream (G711 for example) or using t38, which is generally recommended. When involved in a fax transmission, VoipNow can be the receiver, the sender or just a proxy between two fax machines sending/receiving the fax. No matter what role VoipNow plays, the messages exchanged by the parties involved in the setup and transmission of the fax are similar.

The scenario below describes what happens when a fax message is sent to a VoipNow extension by an external party. In our example, VoipNow is the receiver and has the fax center enabled.

Step-by-step guide

If the fax is not received

Let's see what you should do if the fax is not received.

  1. Verify the settings: the DID must be assigned to the correct extension, the fax must be enabled on the extension, you need to have enough disk space for faxes, etc.
  2. If you've got all that covered, take a tcpdump capture of the fax. For fax transmission over t38, VoipNow uses udp ports 4000-5999 as defined in /etc/asterisk/udptl.conf:

    udptlstart=4000
    udptlend=5999

    The other party may use different ports. So, the best way to capture a fax is to use a tcpdump command with a udp filter.

    tcpdump -nni any -s 0 udp -w /usr/local/voipnow/admin/htdocs/fax.pcap

    The correct sequence is: 1) start the capture; 2) send the fax; 3) wait for it to work or fail; 4) stop the capture.

  3. Once the capture is done, you can download it with from the VoipNow server where it has been taken.

    https://<VoipNow_IP>/fax.pcap
  4. Open the capture using Wireshark. Go to Telephony >> Voip Calls and you will see a list of all the calls in the capture. You can identify the fax by the phone numbers used for sending / receiving the fax message. In our case, it was a fax from 2007 to 3004.



  5. Select the fax and click Flow. In our example, we have a fax answered by VoipNow, so we only have one leg of this call: between the caller and the VoipNow server. If 3004 had been assigned to a fax machine, we would have had a second leg: from 2007 to the extension assigned to 3004. In such cases, select both legs of the call and then click Flow.

  6. You will see a graph showing the SIP and t38 negotiation between the two parties, the sender (10.150.20.13) and the receiver (10.150.20.14). 

The Flow

Here are some screenshots of the entire flow. For a better view, we split the capture of the call.  

  1. First the call is established over SIP, as a regular voice call. Then VoipNow generates a re-INVITE for t38 and the caller accepts it.
  2. If the operation is successful, the negotiation over t38 begins. If the operation fails, the fax either won't be sent, or it will be sent over an audio stream. 

    At this point, you should check the following: 
  • If the first INVITE is rejected by the VoipNow server, ensure that the caller sends the fax to the correct DID; check if 10.150.20.13 is in the accept list of the channel where 3004 is placed. If the call fails here, then this is not a fax-related issue, because regular calls would not work either.
  • If the t38 re-INVITE is rejected with an "Unsupported media" message, then the sender may not support t38. Make sure t38 is enabled on their side. 

    If our example would have been about an outgoing fax, then the first INVITE would have been sent by VoipNow. If you don't see it in the capture, you might be having configuration issues like bad outgoing routing rules, channel costs, and so on. An Asterisk log will help you identify the exact issue.

  • If things so far went OK, this is when the t38 negotiation starts:
It's not necessary for the t38 negociation to happen between the same IPs as the SIP signalling. The two parties can establish this negotiation between different IPs. These IP addresses are mentioned in the "Connection Information" header in the SDP from the t38 INVITE/200OK.

The fax flow is the following:

  1. The receiver (VoipNow) sends a "ced" (Fax answering tone) message
  2. The sender sends a "cng" (Origination fax calling tone) message.
  3. The handshake starts with the receiver sending a "DIS" (Digital Identification Signal) message stating its terminating capabilities.
  4. The sender responds with a "DCS" (Digital Command Signal) message, which indicates the transmission mode that will be used by the sender.
  5. The receiver sends a "CFR" (Confirmation To Receive). This indicates that it's ready to receive the fax.
  6. The sender will now begin to send the fax.
  7. If there are several pages in the fax message, a "MPS" (multipage signal) message will be sent after each page. 
  8. The receiver sends a "MCF" (Message Confirmation) after receiving each page.
  9. Once all pages are sent, an "EOP" (End Of Procedure) message is sent.
  10. The caller will disconnect the call with a "DCN" (Disconnect) message.

This flow should not vary too much. The CED and CNG messages are optional, and the MPS will appear only for multi-page faxes. If one of the parties does not send a message, the other will retry sending the previous one until it times out.

For example, if we send the DIS and do not receive a DCS, we'll try until timeout. This indicates an issue on the sender side. If the issue is on the sender side, you need to tell the sender to check its settings. If the problem is on the VoipNow side, you can continue troubleshooting with an Asterisk log.

Creating an Asterisk log

To create an Asterisk log:

  1. Add the "fax" flag in the /etc/asterisk/logger.conf file.
  2. Reload the logger with asterisk -rx "logger reload":

    console => notice,warning,error,fax
  3. Then log the fax with:

    asterisk -rcvvvvvvvvvvvvvvvvvvvvvvv

This log should offer clues as to why a certain message isn't sent by Asterisk.

If the previous fax was successfully sent, the call returns to a regular audio call and is hung up.

Make sure the call ends properly with a BYE, followed by a 200 OK message. Otherwise, you might get stuck calls in Kamailio.

#trackbackRdf ($trackbackUtils.getContentIdentifier($page) $page.title $trackbackUtils.getPingUrl($page))

Except where otherwise noted, content in this space is licensed under a Creative Commons Attribution 4.0 International.