1####### Routing Logic ########
2
3
4# Main SIP request routing logic
5# - processing of any incoming SIP request starts with this route
6# - note: this is the same as route { ... }
7request_route {
8
9	# per request initial checks
10	route(REQINIT);
11
12	# NAT detection
13	route(NATDETECT);
14
15	# CANCEL processing
16	if (is_method("CANCEL")) {
17		if (t_check_trans()) {
18			route(RELAY);
19		}
20		exit;
21	}
22
23	# handle requests within SIP dialogs
24	route(WITHINDLG);
25
26	### only initial requests (no To tag)
27
28	# handle retransmissions
29	if(t_precheck_trans()) {
30		t_check_trans();
31		exit;
32	}
33	t_check_trans();
34
35	# authentication
36	route(AUTH);
37
38	# record routing for dialog forming requests (in case they are routed)
39	# - remove preloaded route headers
40	remove_hf("Route");
41	if (is_method("INVITE|SUBSCRIBE"))
42		record_route();
43
44	# account only INVITEs
45	if (is_method("INVITE")) {
46		setflag(FLT_ACC); # do accounting
47	}
48
49	# dispatch requests to foreign domains
50	route(SIPOUT);
51
52	### requests for my local domains
53
54	# handle registrations
55	route(REGISTRAR);
56
57	if ($rU==$null) {
58		# request with no Username in RURI
59		sl_send_reply("484","Address Incomplete");
60		exit;
61	}
62
63	# user location service
64	route(LOCATION);
65}
66
67
68route[RELAY] {
69	# enable additional event routes for forwarded requests
70	# - serial forking, RTP relaying handling, a.s.o.
71	if (is_method("INVITE|BYE|SUBSCRIBE|UPDATE")) {
72		if(!t_is_set("branch_route")) t_on_branch("MANAGE_BRANCH");
73	}
74	if (is_method("INVITE|SUBSCRIBE|UPDATE")) {
75		if(!t_is_set("onreply_route")) t_on_reply("MANAGE_REPLY");
76	}
77	if (is_method("INVITE")) {
78		if(!t_is_set("failure_route")) t_on_failure("MANAGE_FAILURE");
79	}
80
81	if (!t_relay()) {
82		sl_reply_error();
83	}
84	exit;
85}
86
87# Per SIP request initial checks
88route[REQINIT] {
89#!ifdef WITH_ANTIFLOOD
90	# flood dection from same IP and traffic ban for a while
91	# be sure you exclude checking trusted peers, such as pstn gateways
92	# - local host excluded (e.g., loop to self)
93	if(src_ip!=myself) {
94		if($sht(ipban=>$si)!=$null) {
95			# ip is already blocked
96			xdbg("request from blocked IP - $rm from $fu (IP:$si:$sp)\n");
97			exit;
98		}
99		if (!pike_check_req()) {
100			xlog("L_ALERT","ALERT: pike blocking $rm from $fu (IP:$si:$sp)\n");
101			$sht(ipban=>$si) = 1;
102			exit;
103		}
104	}
105	if($ua =~ "friendly-scanner") {
106		sl_send_reply("200", "OK");
107		exit;
108	}
109#!endif
110
111	if (!mf_process_maxfwd_header("10")) {
112		sl_send_reply("483","Too Many Hops");
113		exit;
114	}
115
116	if(is_method("OPTIONS") && uri==myself && $rU==$null) {
117		sl_send_reply("200","Keepalive");
118		exit;
119	}
120
121	if(!sanity_check("1511", "7")) {
122		xlog("Malformed SIP message from $si:$sp\n");
123		exit;
124	}
125}
126
127# Handle requests within SIP dialogs
128route[WITHINDLG] {
129	if (!has_totag()) return;
130
131	# sequential request withing a dialog should
132	# take the path determined by record-routing
133	if (loose_route()) {
134		route(DLGURI);
135		if (is_method("BYE")) {
136			setflag(FLT_ACC); # do accounting ...
137			setflag(FLT_ACCFAILED); # ... even if the transaction fails
138		}
139		else if ( is_method("ACK") ) {
140			# ACK is forwarded statelessly
141			route(NATMANAGE);
142		}
143		else if ( is_method("NOTIFY") ) {
144			# Add Record-Route for in-dialog NOTIFY as per RFC 6665.
145			record_route();
146		}
147		route(RELAY);
148		exit;
149	}
150	if ( is_method("ACK") ) {
151		if ( t_check_trans() ) {
152			# no loose-route, but stateful ACK;
153			# must be an ACK after a 487
154			# or e.g. 404 from upstream server
155			route(RELAY);
156			exit;
157		} else {
158			# ACK without matching transaction ... ignore and discard
159			exit;
160		}
161	}
162	sl_send_reply("404", "Not here");
163	exit;
164}
165
166# Handle SIP registrations
167route[REGISTRAR] {
168	if (!is_method("REGISTER")) return;
169	if(isflagset(FLT_NATS)) {
170		setbflag(FLB_NATB);
171#!ifdef WITH_NATSIPPING
172		# do SIP NAT pinging
173		setbflag(FLB_NATSIPPING);
174#!endif
175	}
176	if (!save("location"))
177		sl_reply_error();
178
179	exit;
180}
181
182# User location service
183route[LOCATION] {
184	if (!lookup("location")) {
185		$var(rc) = $rc;
186		t_newtran();
187		switch ($var(rc)) {
188			case -1:
189			case -3:
190				send_reply("404", "Not Found");
191				exit;
192			case -2:
193				send_reply("405", "Method Not Allowed");
194				exit;
195		}
196	}
197
198	# when routing via usrloc, log the missed calls also
199	if (is_method("INVITE")) {
200		setflag(FLT_ACCMISSED);
201	}
202
203	route(RELAY);
204	exit;
205}
206
207
208# IP authorization and user uthentication
209route[AUTH] {
210#!ifdef WITH_AUTH
211
212#!ifdef WITH_IPAUTH
213	if((!is_method("REGISTER")) && allow_source_address()) {
214		# source IP allowed
215		return;
216	}
217#!endif
218
219	if (is_method("REGISTER") || from_uri==myself) {
220		# authenticate requests
221		if (!auth_check("$fd", "subscriber", "1")) {
222			auth_challenge("$fd", "0");
223			exit;
224		}
225		# user authenticated - remove auth header
226		if(!is_method("REGISTER|PUBLISH"))
227			consume_credentials();
228	}
229	# if caller is not local subscriber, then check if it calls
230	# a local destination, otherwise deny, not an open relay here
231	if (from_uri!=myself && uri!=myself) {
232		sl_send_reply("403","Not relaying");
233		exit;
234	}
235
236#!endif
237	return;
238}
239
240# Caller NAT detection
241route[NATDETECT] {
242#!ifdef WITH_NAT
243	force_rport();
244	if (nat_uac_test("19")) {
245		if (is_method("REGISTER")) {
246			fix_nated_register();
247		} else {
248			if(is_first_hop())
249				set_contact_alias();
250		}
251		setflag(FLT_NATS);
252	}
253#!endif
254	return;
255}
256
257# RTPProxy control
258route[NATMANAGE] {
259#!ifdef WITH_NAT
260	if (is_request()) {
261		if(has_totag()) {
262			if(check_route_param("nat=yes")) {
263				setbflag(FLB_NATB);
264			}
265		}
266	}
267	if (!(isflagset(FLT_NATS) || isbflagset(FLB_NATB)))
268		return;
269
270	rtpproxy_manage("co");
271
272	if (is_request()) {
273		if (!has_totag()) {
274			if(t_is_branch_route()) {
275				add_rr_param(";nat=yes");
276			}
277		}
278	}
279	if (is_reply()) {
280		if(isbflagset(FLB_NATB)) {
281			set_contact_alias();
282		}
283	}
284#!endif
285	return;
286}
287
288# URI update for dialog requests
289route[DLGURI] {
290#!ifdef WITH_NAT
291	if(!isdsturiset()) {
292		handle_ruri_alias();
293	}
294#!endif
295	return;
296}
297
298# Routing to foreign domains
299route[SIPOUT] {
300	if (uri==myself) return;
301
302	append_hf("P-hint: outbound\r\n");
303	route(RELAY);
304	exit;
305}
306
307# Manage outgoing branches
308branch_route[MANAGE_BRANCH] {
309	xdbg("new branch [$T_branch_idx] to $ru\n");
310	route(NATMANAGE);
311}
312
313# Manage incoming replies
314onreply_route[MANAGE_REPLY] {
315	xdbg("incoming reply\n");
316	if(status=~"[12][0-9][0-9]")
317		route(NATMANAGE);
318}
319
320# Manage failure routing cases
321failure_route[MANAGE_FAILURE] {
322	route(NATMANAGE);
323
324	if (t_is_canceled()) {
325		exit;
326	}
327}
328