For sipglobal, sip, handle multiple domain and localnet settings. Add the local...
[project/luci.git] / contrib / package / asterisk-xip / files / uci / sipiaxconf
1 #!/bin/sh
2 # Sip / IAX extensions
3
4 # Add to internal extensions
5 add_extension() {
6         logdebug 1 "Adding $1/$2 extension to $3"
7         eval "local ext=\"\${dialplan_ext_$3}\""
8         [ -z "${ext}" ] && append dialplan_exts "$3" " "
9         local lower=`echo $1|tr [A-Z] [a-z]`
10         eval "local ext=\"\${${lower}_last_extension}\""
11         [ -z "${ext}" ] && eval "${lower}_last_extension=\"$3\""
12         append dialplan_ext_$3 $1/${2} "&"
13 }
14
15 check_append_local() {
16         local extension="${1}"
17         logdebug 3 "added local context for ${1}"
18         eval "local isadded=\"\${dialplan_add_local_${extension}-0}\""
19         if [ "$isadded" != "1" ] ; then
20                 logdebug 3 "Not added before - adding"
21                 eval "dialplan_add_local_${extension}=1"
22                 append dialplan_locals "$extension"
23                 eval  "dialplan_local_${1}_context=\"${2}\""
24                 eval  "dialplan_local_${1}_selfmailbox=\"${3}\""
25                 eval  "dialplan_local_${1}_mailbox=\"${4}\""
26                 return 0
27         else
28                 return 1
29         fi
30 }
31 append_dialplan_locals(){
32         for i in ${dialplan_locals} ; do
33                 local extension=$i
34                 for x in context selfmailbox mailbox ; do
35                         eval "x_${x}=\${dialplan_local_${i}_${x}}"
36                 done
37                 local newcontext=local_${extension}
38
39                 if check_add_context ${newcontext} ; then
40                         # add_dialplan_voice ${newcontext} ${x_last_extension} ${x_last_mailbox}
41                         # Make sure as much is matched as possible
42                         #add_dialplan_goto ${newcontext} _[0-9#*+]. ${x_last_context}
43                         # add_dialplan_include ${newcontext}  ${x_last_context}
44
45                         append_dialplan_context ${newcontext} "exten => ${match_all},1,Set(CALLERID(num)=${extension})"
46                         if [ ! -z "${x_mailbox}" ] ; then
47                                 [ "${x_selfmailbox}" = "yes" ] && append_dialplan_context ${newcontext} "exten => ${extension},2,VoiceMailMain(${x_mailbox})"
48                                 [ ! -z "${dialplan_voiceboxext}" ]  && append_dialplan_context ${newcontext} "exten => ${dialplan_voiceboxext},2,VoiceMailMain(${x_mailbox})"
49                         fi
50                         append_dialplan_context ${newcontext} "exten => ${match_all},2,Goto(${x_context},\${EXTEN},1)"
51                 fi
52         done
53 }
54
55 # Sip
56
57 check_add_sipitems() {
58         if [ "${sip_doregister}" == "1" ] ; then
59                 local line="register => ${sip_last_username}@${sip_last_fromdomain}:${sip_last_secret}:${sip_last_username}@${sip_sectionname}"
60                 case ${sip_last_registerextension}  in
61                         -) line="$line/${sip_last_username}" ;;
62                         .*) line="$line/${sip_last_registerextension}" ;;
63                 esac
64                 append sip_register "$line" "$N"
65                 sip_doregister=0
66         fi
67         do_check_add_items sip
68 }
69 check_add_iaxitems() {
70         do_check_add_items iax
71 }
72
73 do_check_add_items(){
74
75         for i in type last_host last_context selfmailbox last_extension last_mailbox ; do
76                 eval "x_${i}=\"\${${1}_${i}-}\""
77         done
78
79         if [ ! -z "${x_last_context}" ] ; then
80                 if [ ! -z "${x_last_extension}" ] ; then
81                         [ "${x_last_context}" = "-" ] && eval "x_last_context=\"\${${1}_opt_context}\""
82                         check_append_local "${x_last_extension}" "${x_last_context}" "${x_selfmailbox}" "${x_last_mailbox}"
83                         x_last_context=local_${x_last_extension}
84                 fi
85                 if [ "${x_last_context}" != "-" ] ; then
86                         append ${1}_sections "context=${x_last_context}" "$N"
87                 fi
88                 if [ "${x_type}" != "user"  -a  -z "${x_last_host}" ] ; then
89                         append ${1}_sections "host=dynamic" "$N"
90                 fi
91         fi
92
93         for i in last_username last_fromdomain last_secret last_username \
94                 sectionname last_fromuser last_context last_extension last_mailbox last_type last_host ; do
95                 eval unset $1_$i
96         done
97
98         eval ${1}_selfmailbox=no
99         eval ${1}_last_registerextension=-
100 }
101
102 reload_sip() {
103         astcmd "sip reload"
104         return 1 # reboot
105 }
106 unload_sip() astcmd "unload chan_sip.so"
107
108 rtp_option_list="rtpstart rtpend rtpdtmftimeout rtcpinterval rtpchecksums"
109 # Validate RTP options
110 valid_rtp_option() {
111         is_in_list $1 ${rtp_option_list}
112 }
113
114 # Validate sip options, depending on context.
115 valid_sipiax_option() {
116         local use_glob=1
117         local use_glob_iax=1
118         local use_glob_sip=1
119         local use_user=1
120         local use_peer=1
121         local use_user_sip=1
122         local use_user_iax=1
123         local use_peer_sip=1
124         local use_peer_iax=1
125         case "$1" in
126                 globalsip)
127                         use_glob_sip=0
128                         use_glob=0 ;;
129                 usersip)
130                         use_glob_sip=0
131                         use_glob=0
132                         use_user=0 ;;
133                 peersip|friendsip)
134                         use_glob_sip=0
135                         use_glob=0
136                         use_user=0
137                         use_peer=0
138                         use_user_sip=0
139                         use_peer_sip=0 ;;
140                 globaliax)
141                         use_glob_iax=0
142                         use_glob=0 ;;
143                 useriax)
144                         use_glob_iax=0
145                         use_glob=0
146                         use_user=0 ;;
147                 peeriax|friendiax)
148                         use_glob_iax=0
149                         use_glob=0
150                         use_user=0
151                         use_peer=0
152                         use_user_iax=0
153                         use_peer_iax=0 ;;
154         esac
155
156         case "$2" in
157                 writeprotect|static) return ${use_glob_iax} ;;
158 # Integer
159                 port|\
160                 maxexpirey|\
161                 rtptimeout|\
162                 rtpholdtimeout|\
163                 defaultexpirey|\
164                 registertimeout|\
165                 registerattempts|\
166                 call-limit) return ${use_glob_sip} ;;
167 # ip addr
168                 bindaddr|\
169                 externip)   return ${use_glob_sip} ;;
170 # net/mask
171                 localnet)   return ${use_glob_sip} ;;
172                 permit|\
173                 deny)  return ${use_user_sip} ;;
174 # Domain name
175                 realm|\
176                 domain)                                 return ${use_glob_sip} ;;
177 # valid context
178                 context)    return ${use_glob} ;;
179 # Mime type
180                 notifymimetype) return ${use_glob_sip} ;;
181 # Yes/No
182                 canreinvite)            return ${use_glob} ;;
183                 nat|allowoverlap|allowsubscribe|allowtransfer|\
184                 videosupport)   return ${use_glob_sip} ;;
185                 pedantic|\
186                 trustrpid|\
187                 promiscredir|\
188                 useclientcode)  return ${use_user_sip} ;;
189 # Enums
190                 dtmfmode)                       return ${use_glob_sip} ;;
191                 type)                                   return ${use_user} ;;
192                 insecure|callingpres|\
193                 progressinband)  return ${use_user_sip} ;;
194 # List 
195                 allow|\
196                 disallow)  return ${use_glob_sip} ;;
197 # Register string
198                 register) return ${use_glob_sip} ;;
199 # String
200                 username|secret|md5secret|host|\
201                 mailbox) return ${use_user} ;;
202                 auth) return ${use_user_iax} ;;
203                 callgroup|pickupgroup|language|accountcode|\
204                 setvar|callerid|amaflags|subscribecontext|\
205                 maxcallbitrate|rfc2833compensate|\
206                 mailbox) return ${use_user_sip};;
207                 template|fromdomain|regexten|fromuser|\
208                 qualify|defaultip|sendrpid|\
209                 outboundproxy) return ${use_peer_sip};;
210                 extension) return 0;;
211                 *) return 1;;
212         esac
213 }
214
215 ast_add_conf sip
216 init_sipconf() {
217         ast_add_reload sip
218         ast_enable_type sipgeneral
219         ast_enable_type sip
220         ast_enable_type target
221
222         sip_opt_port=5060
223         sip_opt_bindaddr=0.0.0.0
224         sip_opt_context=default
225         sip_opt_maxexpirey=3600
226         sip_opt_defaultexpirey=3600
227         sip_opt_notifymimetype=text/plain
228         sip_opt_rtptimeout=60
229         sip_opt_rtpholdtimeout=300
230         config_get WAN_IP wan ipaddr
231         # TODO check why the above does not work all the time
232         if [ -z "${WAN_IP}" ] ; then
233                 config_get WAN_IF wan ifname
234                 WAN_IP=$(ifconfig ${WAN_IF} | grep "inet addr:" | sed 's/^.*inet addr:\([^ ]*\) .*$/\1/')
235         fi
236
237         sip_opt_externip=${WAN_IP}
238
239         sip_opt_realm=asterisk
240         config_get LAN_MASK lan netmask
241         config_get LAN_IP lan ipaddr
242         local LAN_NET=$(/bin/ipcalc.sh $LAN_IP $LAN_MASK | grep NETWORK | cut -d= -f2)
243         sip_opt_localnet_def=$LAN_NET/$LAN_MASK
244         sip_opt_localip=${LAN_IP}
245
246         # default to ulaw only
247         sip_opt_allow=
248         sip_opt_registertimeout=20
249         sip_opt_registerattempts=10
250         sip_opt_canreinvite=no
251
252         sip_sections=
253 }
254
255 sip_list="port bindaddr context maxexpirey defaultexpirey notifymimetype \
256 rtptimeout rtpholdtimeout realm externip"
257
258 create_sipconf() {
259
260         append_dialplan_locals
261
262         file=${DEST_DIR}/sip.conf
263         get_checksum sip_conf $file
264         local isempty=1
265         if [ -z "${sip_sections}" ] ; then
266                 rm -f $file
267                 isempty=2
268         else
269                 [ -z "${sip_opt_domain}" ]  && sip_opt_domain="domain=${sip_opt_realm}"
270
271                 echo "${asteriskuci_gen}[general]" > $file
272                 echo "${sip_opt_domain}" >> "$file"
273                 echo "domain=${sip_opt_localip}" >> "$file"
274                 for i in ${sip_list} ; do
275                         eval value=\$sip_opt_$i
276                         [ ! -z "$value" ] && ( echo "$i=$value" >> $file )
277                 done
278                 [ -z "${sip_opt_localnet}" ] && sip_opt_localnet="localnet=${sip_opt_localnet_def}"
279                 echo "${sip_opt_localnet}" >> "${file}"
280                 echo "disallow=all" >> $file
281                 local rhs="${sip_opt_allow}"
282                 [ -z "$rhs" ] && rhs=ulaw
283                 while [ ! -z "$rhs" ] ; do
284                         cur=${rhs%%,*}
285                         nvar=${rhs#*,}
286                         enable_format ${cur}
287                         echo "allow=${cur}" >> $file
288                         [ "$nvar" == "$rhs" ] && break
289                         rhs=${nvar}
290                 done
291
292                 echo "${N}${sip_register}${N}${N}${sip_sections}" >> $file
293                 unset sip_register
294                 unset sip_sections
295         fi
296         check_checksum "$sip_conf" "$file" || ast_sip_restart=$isempty
297 }
298
299
300 handle_sipgeneral() {
301         option_cb(){
302                 if [ "${1%_LENGTH}" = "${1}" ] ; then
303                         local opt=${1%_ITEM*}
304                         logdebug 4 "SipGeneral option ${opt} $2"
305                         if valid_sipiax_option globalsip ${opt} "$2" ; then
306                                 case "${opt}" in
307                                         host) sip_opt_host="$2"
308                                                 [ -z "${sip_opt_host}" ] && sip_opt_host=dynamic ;;
309                                         allow)    append sip_opt_allow "$2" "," ;;
310                                         domain)   split_append sip_opt_domain domain= "$2" "${N}"  ;;
311                                         localnet) split_append sip_opt_localnet localnet= "$2" "${N}" ;;
312                                         *) eval "sip_opt_$1=\"\$2\"" ;;
313                                 esac
314                         elif valid_rtp_option $1 "$2" ; then
315                                 eval "rtp_opt_$1=\"\$2\""
316                         else
317                                 logerror "Invalid SIP global option: $1"
318                         fi
319                 fi
320         }
321 }
322
323 handle_sip() {
324         check_add sipitems
325         append sip_sections [$1] "$N$N"
326         enable_module chan_sip
327         sip_sectionname=${1#sip_}
328         sip_type=peer
329         sip_doregister=0
330         sip_last_context=-
331         sip_last_doregister=-
332         sip_selfmailbox=no
333         option_cb() {
334                 logdebug 3 "SIP/${sip_sectionname}: '$1' '$2'"
335                 case $1 in
336                         type) sip_type=$2
337                                 append sip_sections "$1=$2" "$N"
338                                 ;;
339                         register) [ "$2" == "yes" ] && sip_doregister=1 ;;
340                         registerextension) eval sip_last_$1="$2";;
341                         allow|allow_ITEM*) split_append sip_sections allow= "$2" "${N}" enable_format ;;
342                         extension|extension_ITEM*)    add_extension SIP ${sip_sectionname} "$2" ;;
343
344                         context)      sip_last_context="$2" ;;
345                         selfmailbox)  sip_selfmailbox="$2" ;;
346                         incoming|incoming_ITEM*)
347                                 add_incoming SIP ${sip_sectionname} "$2" ;;
348                         timeout|prefix|internationalprefix|alwaysinternational|countrycode)
349                                 eval "target_$1_SIP_${sectionname}=\"$2\""
350                         ;;
351                         *_LENGTH) ;;
352                         *)
353                                 eval sip_last_$1="$2"
354                                 local opt=${1%_ITEM*}
355                                 if valid_sipiax_option ${sip_type}sip ${opt} $2 ; then
356                                         append sip_sections "${opt}=$2" "$N"
357                                 else
358                                         logerror "Invalid SIP option for ${sip_type}: ${opt}"
359                                 fi
360                 esac
361         }
362 }
363
364 # rtp.conf
365
366 ast_add_conf rtp
367 init_rtpconf() {
368         ast_add_reload rtp
369         rtp_opt_rtpstart=5000
370         rtp_opt_rtpend=31000
371         rtp_opt_rtpchecksums=
372         rtp_opt_rtpdtmftimeout=
373         rtp_opt_rtcpinterval=5000
374 }
375
376 create_rtpconf() {
377         file=${DEST_DIR}/rtp.conf
378         get_checksum rtp_conf $file
379         local isempty=1
380         if module_enabled chan_sip ; then
381                 echo "${asteriskuci_gen}[general]" > $file
382                 for i in $rtp_option_list ; do
383                         eval "local val=\"\$rtp_opt_$i\""
384                         if [ ! -z "$val" ] ; then
385                                 lhs=$i
386                                 case "$i" in
387                                         rtpdtmftimeout) lhs=dtmftimeout
388                                 esac
389                                 echo "$lhs=$val" >> $file
390                         fi
391                 done
392         else
393                 rm -f $file
394                 isempty=2
395         fi
396
397         check_checksum "$rtp_conf" "$file" || ast_rtp_restart=$isempty
398 }
399 reload_rtp() astcmd "rtp reload"
400 unload_rtp() astcmd "unload rtp"
401
402
403 # Iax
404
405 ast_add_conf iax
406
407 init_iaxconf() {
408         ast_add_reload iax
409         ast_enable_type iaxgeneral
410         ast_enable_type iax
411
412         return 0
413 }
414
415 create_iaxconf() {
416         local file=$DEST_DIR/iax.conf
417         get_checksum iax_conf $file
418         local isempty=1
419         if [ -z "${iax_sections}" ] ; then
420                 rm -f $file
421                 isempty=2
422         else
423                 echo "${asteriskuci_gen}${iax_general}$N$N${iax_sections}" > $file
424         fi
425         check_checksum "$iax_conf" "$file"  || ast_iax_restart=${isempty}
426 }
427
428 handle_iaxgeneral() {
429         iax_general="[general]"
430         option_cb() {
431                 case $1 in
432                         allow_LENGTH) ;;
433                         allow|allow_ITEM*) split_append iax_general allow= "$2" "${N}" enable_format ;;
434                         *)
435                                 if valid_sipiax_option globaliax $1 $2 ; then
436                                         eval "iax_opt_$1=\"$2\""
437                                         append iax_general "$1=$2" "$N"
438                                 else
439                                         logerror "Invalid IAX global option: $1"
440                                 fi ;;
441                 esac
442         }
443 }
444
445 handle_iax() {
446         check_add iaxitems
447         iax_type=peer
448         iax_sectionname="${1#iax_}"
449         append iax_sections "[${iax_sectionname}]" "$N$N"
450         iax_last_context=-
451         iax_selfmailbox=no
452         enable_module chan_iax2
453         option_cb() {
454                 case $1 in
455                         type)
456                                 iax_type=$2
457                                 append iax_sections "type=$2" "$N" ;;
458                         allow_LENGTH|incoming_LENGTH) ;;
459                         allow|allow_ITEM*)
460                                 split_append iax_sections allow= "$2" "${N}" enable_format ;;
461                         extension_LENGTH) ;;
462                         extension|extension_ITEM*)    add_extension IAX ${iax_sectionname} "$2" ;;
463                         context)
464                                 eval iax_last_context="$2" ;;
465                         selfmailbox)
466                                 eval iax_selfmailbox="$2" ;;
467                         incoming|incoming_ITEM*)
468                                 add_incoming IAX ${iax_sectionname} "$2" ;;
469                         timeout|prefix|internationalprefix|alwaysinternational|countrycode)
470                                 eval "target_$1_IAX_${sectionname}=\"$2\"" ;;
471                         *)
472                                 eval iax_last_$1="$2"
473                                 if valid_sipiax_option ${iax_type}iax $1 $2 ; then
474                                         append iax_sections "$1=$2" "$N"
475                                 else
476                                         logerror "Invalid IAX option for ${iax_type}: $1"
477                                 fi
478                 esac
479         }
480 }
481
482 reload_iax() {
483         astcmd "iax2 reload"
484         return 1
485 }
486 unload_iax() astcmd "unload chan_iax2.so"
487
488 handle_target() {
489         # Target name
490         if split_targettype targettype targetname "${1}" ; then
491                 logdebug 4 "Handle target ${targettype}/${targetname} - ${1}"
492                 handle_dialtarget "${targettype}" "${targetname}"
493         else
494                 logerror "No target type specified for target $1"
495         fi
496 }
497
498 # Set up options sip/iax targets for outgoing sip/iax
499 handle_dialtarget() {
500         # Dialzone target option
501         dt_areatype="$1"
502         dt_areaname="$2"
503         logdebug 1 "Dialzone Target for ${dt_areatype}/${dt_areaname}"
504         option_cb(){
505                 logdebug 3 "Option $1='$2' for dialzone target"
506                 case $1 in
507                         timeout|prefix|internationalprefix|alwaysinternational|countrycode)
508                                 eval "target_$1_${dt_areatype}_${dt_areaname}=\"$2\""
509                         ;;
510                         *) 
511                                 logerror "Invalid target for ${dt_areatype}/${dt_areaname}: ${1}"
512                 esac
513         }
514 }
515
516 # vim: ts=2 sw=2 noet foldmethod=indent