SIP/SDP Message Grammar

Compiled by Arjun Roychowdhury and Henning Schulzrinne.

Not up-to-date; use current Internet draft instead for definitive reference. Better tools are now available, such as abnf2html. Volunteers to convert the RFC 3261 grammar are solicited.

Based on RFC 2543,RFC 2327RFC 2616, RFC 1123, RFC 2234, and RFC 2396, Sip Notes and Clarifications.

SIP-message = Request | Response
Request = Request-Line
*( general-header | request-header | entity-header ) double-return     [message-body]
; Note - each header ends with a return and the end of headers is a double return. For line folding, the folded header must begin with  1*( SP | HT )

 

message-body = // Note: This is typically SDP
Request-Line = Method SP Request-URI SP SIP-Version return
SIP-URL = "sip:" [userinfo "@" ] hostport url-parameters [ headers
userinfo = user [ ":" password
user = *( unreserved | escaped | "&" | "=" | "+" | "$" | "," ) 
password = *( unreserved | escaped | "&" | "=" | "+" | "$" | "," ) 
hostport = host [ ":" port
host = hostname | IPv4address
hostname = *(domainlabel "." ) toplabel [ "." ] 
domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum
toplabel = alpha | alpha *( alphanum | "-" ) alphanum
IPv4address = 1*digit "." 1*digit "." 1*digit "." 1*digit
port = * digit ; empty port field is allowed 
url-parameters = *( ";" url-parameter
url-parameter = transport-param | user-param | method-param| ttl-param | maddr-param | other-param
transport-param = "transport=" ( "udp" | "tcp" ) 
ttl-param = "ttl=" ttl
ttl = 1*3 DIGIT ; 0 to 255 
maddr-param = "maddr=" host
user-param = "user=" ( "phone" | "ip" ) 
method-param = "method=" Method
tag-param = "tag=" UUID
UUID = 1*( hex | "-" ) 
other-param = ( token | ( token "=" ( token | quoted-string ))) 
headers = "?"header *( "&" header
header = hname "=" hvalue
hname = 1*uric
hvalue = *uric
uric = reserved | unreserved | escaped
reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | "," 
digits = 1*DIGIT
telephone-subscriber = global-phone-number | local-phone-number
global-phone-number = "+" 1*phonedigit [isdn-subaddress] [post-dial
local-phone-number = 1*(phonedigit | dtmf-digit | pause-character) [isdn-subaddress] [post-dial
isdn-subaddress = ";isub=" 1*phonedigit
post-dial = ";postd=" 1*(phonedigit | dtmf-digit | pause-character
phonedigit = DIGIT | visual-separator
visual-separator = "-" | "." 
pause-character = one-second-pause | wait-for-dial-tone
one-second-pause = "p" 
wait-for-dial-tone = "w" 
dtmf-digit = "*" | "#" | "A" | "B" | "C" | "D" 
general-header = Accept
| Accept-Encoding
| Accept-Language
| Call-ID
| Contact
| CSeq
| Date
| Encryption
| Expires
| From
| Record-Route
| Timestamp
| To
| Via
entity-header = Content-Encoding
| Content-Length
| Content-Type
request-header =

Authorization
| Contact
| Hide
| Max-Forwards
| Organization
| Priority
| Proxy-Authorization
| Proxy-Require
| Route
| Require
| Response-Key
| Subject
| User-Agent
|WWW-Authenticate

response-header = Allow
| Authorization
| Proxy-Authenticate
| Retry-After
| Server
| Unsupported
| Warning
| WWW-Authenticate
Method = "INVITE" | "ACK" | "OPTIONS" | "BYE" | "CANCEL" | "REGISTER" 
Accept = "Accept" ":" #( media-range [ accept-params ] ) 
media-range = ( "*/*" | ( type "/" "*" ) | ( type "/" subtype ) ) *( ";" parameter
parameter = attribute "=" value
attribute = token
value = token | quoted-string
accept-params = ";" "q" "=" qvalue *( accept-extension
accept-extension = ";" token [ "=" (token | quoted-string ) ] 
Accept-Encoding = "Accept-Encoding" ":" 1#( content-coding
codings = ( content-coding | "*" ) 
content-coding = token
Accept-Language = "Accept-Language" ":" 1#( language-range [ ";" "q" "=" qvalue ] ) 
language-range = ( ( 1*8ALPHA *( "-" 1*8ALPHA ) ) | "*" ) 
Proxy-Authorization = "Proxy-Authorization" ":" credentials
Proxy-Authenticate = "Proxy-Authenticate" ":" 1#challenge
User-Agent = "User-Agent" ":" 1*( product | comment
Server = "Server" ":" 1*( product | comment
Response = Status-Line *( general-header | response-header | entity-header ) double-return [ message-body ] ; Note - each header ends with a return and the end of headers is a double return. For line folding, the folded header must begin with  1*( SP | HT )
Status-Line = SIP-version SP Status-Code     SP Reason-Phrase
SIP-version = "SIP/2.0" 
Status-Code = Informational
| Success
| Redirection
| Client-Error
| Server-Error
| Global-Failure
| extension-code
extension-code = 3 DIGIT
Reason-Phrase = *<TEXT-UTF8, excluding CR, LF
Informational = "100" Trying 
| "180" ; Ringing 
| "181"  ; Call Is Being Forwarded 
| "182"  ; Queued 
Success = "200" ; OK 
Redirection = "300" ; Multiple Choices 
| "301" ; Moved Permanently 
| "302" ; Moved Temporarily 
| "303" ; See Other 
| "305" ; Use Proxy 
| "380" ; Alternative Service 
Client-Error = "400"  ; Bad Request 
| "401"  ; Unauthorized 
| "402"  ; Payment Required 
| "403" ; Forbidden 
| "404" ; Not Found 
| "405"  ; Method Not Allowed 
| "406"  ; Not Acceptable 
| "407"  ; Proxy Authentication Required 
| "408"  ; Request Timeout 
| "409"  ; Conflict 
| "410"  ; Gone 
| "411"  ; Length Required 
| "413"  ; Request Entity Too Large 
| "414"  ; Request-URI Too Large 
| "415"  ; Unsupported Media Type 
| "420"  ; Bad Extension 
| "480"  ; Temporarily not available 
| "481"  ; Call Leg/Transaction Does Not Exist 
| "482"  ; Loop Detected 
| "483"  ; Too Many Hops 
| "484" ; Address Incomplete 
| "485"  ; Ambiguous 
| "486" ; Busy Here 
Server-Error = "500" ; Internal Server Error 
| "501" ; Not Implemented 
| "502"  ; Bad Gateway 
| "503"  ; Service Unavailable 
| "504"  ; Gateway Time-out 
| "505"  ; SIP Version not supported 
Global-Failure = "600" ; Busy Everywhere 
| "603"  ; Decline 
| "604"  ; Does not exist anywhere 
| "606" ; Not Acceptable 
message-header = field-name ":" [ field-value ] CRLF
field-name = token
field-value = *(field-content | LWS
field-content = <the OCTETs making up the field-value and consisting of either *TEXT-UTF8 or combinations of token, separators, and quoted-string
Allow = "Allow" ":" 1#Method
Call-ID = ( "Call-ID" | "i" ) ":" token
local-id = 1*uric
Contact = ( "Contact" | "m" ) ":" ("*" | (1# ((name-addr | addr-spec ) [ *( ";" contact-params ) ] [ comment ] ))) 
name-addr = [ display-name ] "<" addr-spec ">" 
addr-spec = SIP-URL | URI
display-name = *token | quoted-string
contact-params = "q" "=" qvalue| ("action" "=" "proxy" | "redirect") |( "expires" "=" delta-seconds | <"> SIP-date <">) | extension-attribute
extension-attribute = extension-name [ "=" extension-value ]
Content-Encoding = ( "Content-Encoding" | "e" ) ":" 1#content-coding
Content-Length = ( "Content-Length" | "l" ) ":" 1*DIGIT
Content-Type = ( "Content-Type" | "c" ) ":"media-type
media-type = type "/"subtype *( ";" parameter
type = token
subtype = token
CSeq = "CSeq" ":" 1*DIGIT Method
Date = "Date:" SIP-date
SIP-date = rfc1123-date
Encryption = "Encryption" ":"encryption-scheme 1*SP #encryption-params
encryption-scheme = token
encryption-params = token "=" ( token | quoted-string
Expires = "Expires" ":" ( SIP-date | delta-seconds
From = ( "From" | "f" ) ":" ( name-addr | addr-spec ) *( ";" addr-params )  *(";" extension-params)
addr-params = tag-param
tag-param = "tag="UUID
Hide = "Hide" ":" ( "route" | "hop" ) 
Max-Forwards = "Max-Forwards" ":" 1*DIGIT
Organization = "Organization" ":" *TEXT-UTF8
Priority = "Priority" ":"priority-value
priority-value = "emergency" | "urgent" | "normal" | "non-urgent" 
Record-Route = "Record-Route" ":" 1# name-addr
Require = "Require" ":" 1#option-tag
Proxy-Require = "Proxy-Require" ":" 1#option-tag
option-tag = token
Response-Key = "Response-Key" ":" key-scheme 1*SP #key-param
key-scheme = token
key-param = token "=" ( token | quoted-string
Retry-After = "Retry-After" ":"( SIP-date | delta-seconds ) [ comment ] [ ";" "duration" "=" delta-seconds
Route = "Route" ":" 1#name-addr
Subject = ( "Subject" | "s" ) ":" *TEXT-UTF8
Timestamp = "Timestamp" ":" *(DIGIT) [ "." *(DIGIT) ] [ delay
delay = *(DIGIT) [ "." *(DIGIT) ] 
To = ( "To" | "t" ) ":" (name-addr | addr-spec ) *( ";" addr-params ) *(";" extension-params) // Extension params are allowed in From to and Via
Unsupported = "Unsupported" ":" 1#option-tag
Via = ( "Via" | "v") ":" 1#(sent-protocol sent-by *( ";" via-params ) [ comment ] ) *(";" extension-params) // Extension params are allowed in From to and Via
via-params = via-hidden | via-ttl | via-maddr| via-received | via-branch
via-hidden = "hidden" 
via-ttl = "ttl" "=" ttl
via-maddr = "maddr" "=" maddr // Note: maddr not defined but it should be host
via-received = "received" "="host
via-branch = "branch" "=" token
sent-protocol = protocol-name "/" protocol-version "/" transport
protocol-name = "SIP" | token
protocol-version = token
transport = "UDP" | "TCP" | token
sent-by = (host [ ":" port ] ) | ( concealed-host
concealed-host = token
Warning = "Warning" ":" 1#warning-value
warning-value = warn-code SP warn-agent SP warn-text
warn-code = 3 DIGIT
warn-agent = (host [ ":" port ] ) | pseudonym ; the name or pseudonym of the server adding the Warning header, for use in debugging 
pseudonym = token
warn-text = quoted-string
WWW-Authenticate = "WWW-Authenticate" ":"  1#challenge
auth-scheme = token
challenge = auth-scheme 1*SP realm *("," auth-param)
realm = "realm" "=" realm-value
auth-param = token "=" string
credentials = basic-credentials | (auth-scheme #(auth-params))
basic-credentials = "Basic" SP basic-cookie
basic-cookie = <encrypted string>
pgp-challenge = * (pgp-params
pgp-params = realm | pgp-version | pgp-algorithm | nonce
realm = "realm" "="realm-value
realm-value = quoted-string
pgp-version = "version" "=" <"> digit *( "." digit ) *letter <">
pgp-algorithm = "algorithm" "=" ( "md5" | "sha1" |token
nonce = "nonce" "=" nonce-value
nonce-value = quoted-string
Authorization = "Authorization" ":" credentials 
pgp-response = realm | pgp-version | pgp-signature| signed-by | nonce
pgp-signature = "signature" "="quoted-string
signed-by = "signed-by" "=" <"> URI <">
pgp-eparams = 1# ( pgp-version | pgp-encoding| pgp-key
pgp-encoding = "encoding" "=" "ascii" | token
pgp-key = "key" "=" quoted-string
OCTET = %x00-ff ; any 8-bit sequence of data 
CHAR = %x00-7f ; any US-ASCII character (octets 0 - 127) 
upalpha = "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | "J" | "K" | "L" | "M" | "N" | "O" | "P" | "Q" | "R" | "S" | "T" | "U" | "V" | "W" | "X" | "Y" | "Z" 
lowalpha = "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j" | "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" | "s" | "t" | "u" | "v" | "w" | "x" | "y" | "z" 
alpha = lowalpha | upalpha
digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" 
alphanum = alpha | digit
CTL = %x00-1f | 0x7f ; any US-ASCII control character (octets 0 -- 31) and DEL (127) 
CR = %d13  ; US-ASCII CR, carriage return character 
LF = %d10  ; US-ASCII LF, line feed character 
SP = %d32  ; US-ASCII SP, space character 
HT = %d09 ; US-ASCII HT, horizontal tab character 
return = CR | LF | CRLF ; typically the end of a line 
unreserved = alphanum | mark
double-return = (CR CR) | (LF LF) | (CR LF CR LF)
mark = "-" | "_" | "." | "!" | "~" | "*" | " ' " | "(" | ")" 
escaped = "%"hex hex
LWS = [CRLF] 1*( SP | HT ) ; linear whitespace 
TEXT-UTF8 = <any UTF-8 character encoding, except CTLs, but including LWS
hex = "A" | "B" | "C" | "D" | "E" | "F" | "a" | "b" | "c" | "d" | "e" | "f" | digit
token = 1* (alphanum | "-" | "." | "$" | "%" | "*" | "_" | "+" | "~" | "`" | "'") 
separators = "(" | ")" | "<" | "" | "@" | "," | ";" | ":" | "\" | "<" | "/" | "[" | "]" | "?" | "=" | "{" | "}" | SP | HT
comment = "(" *(ctext| quoted-pair | comment) ")" 
ctext = <anyTEXT-UTF8 excluding "(" and ")" >
quoted-string = ( <"> *(qdtext | quoted-pair ) <"> ) 
qdtext = <anyTEXT-UTF8 except <"> > 
quoted-pair = "\"CHAR
delta-seconds = 1*DIGIT // This is not spec. in 2543 and no reference is given (its in H.3.3.2) 
qvalue = ( "0" [ "." 0*3 DIGIT ] ) | ( "1" [ "." 0*3("0") ] ) 
URI-reference = ([ absoluteURI | relativeURI] [ "#" fragment] ) | (sip-url // According to 2453:4.3 - ReqURI is SIPUri (without certain tokens) or GeneralURI 
absoluteURI = scheme":" ( hier_part | opaque_part
relativeURI = (net_path | abs_path | rel_path ) [ "?" query
hier_part = ( net_path | abs_path ) [ "?" query
opaque_part = uric_no_slash *uric
uric_no_slash = unreserved | escaped | ";" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | "," 
net_path = "//"authority [ abs_path
abs_path = "/"path_segments
rel_path = rel_segment [ abs_path
rel_segment = 1*(unreserved | escaped | ";" | "@" | "&" | "=" | "+" | "$" | "," ) 
scheme = alpha *( alpha | digit | "+" | "-" | "." ) 
authority = server_H | reg_name
reg_name = 1*( unreserved | escaped | "$" | "," | ";" | ":" | "@" | "&" | "=" | "+" ) 
server_H = [ [ userinfo_H "@" ] hostport
userinfo_H = *( unreserved | escaped | ";" | ":" | "&" | "=" | "+" | "$" | "," ) 
path = [ abs_path | opaque_part
path_segments = segment *( "/" segment
segment = *pchar *( ";" param
param = *pchar
pchar = unreserved | escaped | ":" | "@" | "&" | "=" | "+" | "$" | "," 
query = *uric
fragment = *uric
product = token ["/" product-version
product-version = token
rfc1123-date = wkday "," SP date1SP time SP "GMT" 
date1 = 2DIGIT SP month SP 4DIGIT ; day month year (e.g., 02 Jun 1982) 
time = 2 DIGIT ":" 2 DIGIT ":" 2DIGIT ; 00:00:00 - 23:59:59 
wkday = "Mon" | "Tue" | "Wed"| "Thu" | "Fri" | "Sat" | "Sun" 
month = "Jan" | "Feb" | "Mar" | "Apr" | "May" | "Jun" | "Jul" | "Aug" | "Sep" | "Oct" | "Nov" | "Dec"
announcement = proto-version
origin-field
session-name-field
information-field
uri-field
email-fields
phone-fields
connection-field
bandwidth-fields
time-fields
key-field
attribute-fields
media-descriptions
proto-version
= "v=" 1*DIGIT return ;this memo describes version 0
origin-field = "o=" username space sess-id space sess-version space
nettype space addrtype space
addr return
session-name-field
= "s=" text return
information-field
=   ["i=" text return]
uri-field = ["u=" uri return]
email-fields
= *("e=" email-address return)
phone-fields
= *("p=" phone-number return)
connection-field  
= ["c=" nettype space addrtype space
connection-address return]
;a connection field must be present
;in every media description or at the
;session-level
bandwidth-fields
= *("b=" bwtype ":" bandwidth return)
time-fields
= 1*( "t=" start-time space stop-time
*(return repeat-fields) return)
[zone-adjustments return]
repeat-fields
= "r=" repeat-interval space typed-time
1*(space typed-time)
zone-adjustments
= time space ["-"] typed-time
*(space time space ["-"] typed-time)
key-field
= ["k=" key-type return]
key-type
= "prompt" | "clear:" key-data | "base64:" key-data |"uri:" uri
key-data
= email-safe | "~" | "
attribute-fields = *("a=" attribute return)
media-field = "m=" media space port ["/" integer]
space proto 1*(space fmt) return
media-descriptions
= *( media-field
information-field
*(connection-field)
bandwidth-fields
key-field
attribute-fields )
media = 1*(alpha-numeric) ;typically "audio", "video", "application"
;or "data"
fmt
= 1*(alpha-numeric) ;typically an RTP payload type for audio
;and video media
proto

= 1*(alpha-numeric) ;typically "RTP/AVP" or "udp" for IP4
port
= 1*(DIGIT) ;should in the range "1024" to "65535" inclusive
;for UDP based media
attribute
= (att-field ":" att-value) | att-field
att-field
= 1*(alpha-numeric)
att-value
= byte-string
sess-id 
= 1*(DIGIT) ;should be unique for this originating username/host
sess-version
= 1*(DIGIT) ;0 is a new session
connection-address
= multicast-address
| addr
multicast-address  
= 3*(decimal-uchar ".") decimal-uchar "/" ttl
[ "/" integer ]
;multicast addresses may be in the range
;224.0.0.0 to 239.255.255.255
start-time = time | "0"
stop-time = time | "0"
time = POS-DIGIT 9*(DIGIT) ;sufficient for 2 more centuries
repeat-interval
= typed-time
typed-time
= 1*(DIGIT) [fixed-len-time-unit]
fixed-len-time-unit = "d" | "h" | "m" | "s"
bwtype
= 1*(alpha-numeric)
bandwidth
= 1*(DIGIT)
username
= safe ;pretty wide definition, but doesn't include space
email-address
= email | email "(" email-safe ")" |
email-safe "<" email ">"
email
= ; defined in RFC822
phone-number
= phone | phone "(" email-safe ")" |
email-safe "<" phone ">"
phone
= "+" POS-DIGIT 1*(space | "-" | DIGIT) ;there must be a space or hyphen between the
;international code and the rest of the number.
nettype = "IN" ;list to be extended
addrtype = "IP4" | "IP6" ;list to be extended
addr
= FQDN | unicast-address
FQDN
= 4*(alpha-numeric|"-"|".") ;fully qualified domain name as specified in RFC1035
unicast-address
= IP4-address | IP6-address
IP4-address
= b1 "." decimal-uchar "." decimal-uchar "." b4
b1
= decimal-uchar   ;less than "224"; not "0" or "127"
b4
= decimal-uchar    ;not "0"
IP6-address
= ;to be defined
text


= byte-string ;default is to interpret this as I0-10646 UTF8
;ISO 8859-1 requires a "a=charset:ISO-8859-1"
;session-level attribute to be used
byte-string
= 1*(0x01..0x09|0x0b|0x0c|0x0e..0xff) ;any byte except NUL, CR or LF
decimal-uchar = DIGIT
| POS-DIGIT DIGIT
| ("1" 2*(DIGIT))
| ("2" ("0"|"1"|"2"|"3"|"4") DIGIT)
| ("2" "5" ("0"|"1"|"2"|"3"|"4"|"5"))
integer
= POS-DIGIT *(DIGIT)
POS-DIGIT
= "1"|"2"|"3"|"4"|"5"|"6"|"7"|"8"|"9"
email-safe
= safe | space | tab
safe
= alpha-numeric |
"'" | "'" | "-" | "." | "/" | ":" | "?" | """ |
"#" | "$" | "&" | "*" | ";" | "=" | "@" | "[" |
"]" | "^" | "_" | "`" | "{" | "|" | "}" | "+" |
"~" | "
space = SP

 


Last updated  by Henning Schulzrinne