Browse code

core, lib, modules: restructured source code tree

- new folder src/ to hold the source code for main project applications
- main.c is in src/
- all core files are subfolder are in src/core/
- modules are in src/modules/
- libs are in src/lib/
- application Makefiles are in src/
- application binary is built in src/ (src/kamailio)

Daniel-Constantin Mierla authored on 07/12/2016 11:03:51
Showing 1 changed files
1 1
deleted file mode 100644
... ...
@@ -1,694 +0,0 @@
1
-/* 
2
- * Copyright (C) 2010 iptelorg GmbH
3
- *
4
- * Permission to use, copy, modify, and distribute this software for any
5
- * purpose with or without fee is hereby granted, provided that the above
6
- * copyright notice and this permission notice appear in all copies.
7
- *
8
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15
- */
16
-
17
-/** Kamailio core :: raw socket functions.
18
- *  @file raw_sock.c
19
- *  @ingroup core
20
- *  Module: @ref core
21
- */
22
-
23
-#ifdef USE_RAW_SOCKS
24
-
25
-#include "compiler_opt.h"
26
-#include "ip_addr.h"
27
-#include "dprint.h"
28
-#include "str.h"
29
-#include "rand/fastrand.h"
30
-#include "globals.h"
31
-
32
-#include <errno.h>
33
-#include <string.h>
34
-#include <unistd.h>
35
-#include <sys/types.h>
36
-#include <fcntl.h>
37
-#include <sys/socket.h>
38
-#include <netinet/in.h>
39
-#include <netinet/in_systm.h>
40
-#include <arpa/inet.h>
41
-#ifndef __USE_BSD
42
-#define __USE_BSD  /* on linux use bsd version of iphdr (more portable) */
43
-#endif /* __USE_BSD */
44
-#include <netinet/ip.h>
45
-#define __FAVOR_BSD /* on linux use bsd version of udphdr (more portable) */
46
-#include <netinet/udp.h>
47
-
48
-#include "raw_sock.h"
49
-#include "cfg/cfg.h"
50
-#include "cfg_core.h"
51
-
52
-
53
-#if defined (__OS_freebsd) || defined (__OS_netbsd) || defined(__OS_openbsd) \
54
-	|| defined (__OS_darwin)
55
-/** fragmentation is done by the kernel (no need to do it in userspace) */
56
-#define RAW_IPHDR_INC_AUTO_FRAG
57
-#endif /* __OS_* */
58
-
59
-/* macros for converting values in the expected format */
60
-#if defined (__OS_freebsd) || defined (__OS_netbsd) || defined (__OS_darwin)
61
-/* on freebsd and netbsd the ip offset (along with flags) and the
62
-   ip header length must be filled in _host_ bytes order format.
63
-   The same is true for openbsd < 2.1.
64
-*/
65
-/** convert the ip offset in the format expected by the kernel. */
66
-#define RAW_IPHDR_IP_OFF(off) (unsigned short)(off)
67
-/** convert the ip total length in the format expected by the kernel. */
68
-#define RAW_IPHDR_IP_LEN(tlen) (unsigned short)(tlen)
69
-
70
-#else /* __OS_* */
71
-/* linux, openbsd >= 2.1 a.s.o. */
72
-/** convert the ip offset in the format expected by the kernel. */
73
-#define RAW_IPHDR_IP_OFF(off)  htons((unsigned short)(off))
74
-/** convert the ip total length in the format expected by the kernel. */
75
-#define RAW_IPHDR_IP_LEN(tlen) htons((unsigned short)(tlen))
76
-
77
-#endif /* __OS_* */
78
-
79
-int raw_ipip = 0; /* set if raw socket is in capture mode for IPIP */
80
-
81
-
82
-/** create and return a raw socket.
83
- * @param proto - protocol used (e.g. IPPROTO_UDP, IPPROTO_RAW)
84
- * @param ip - if not null the socket will be bound on this ip.
85
- * @param iface - if not null the socket will be bound to this interface
86
- *                (SO_BINDTODEVICE). This is supported only on linux.
87
- * @param iphdr_incl - set to 1 if packets send on this socket include
88
- *                     a pre-built ip header (some fields, like the checksum
89
- *                     will still be filled by the kernel, OTOH packet
90
- *                     fragmentation has to be done in user space).
91
- * @return socket on success, -1 on error
92
- */
93
-int raw_socket(int proto, struct ip_addr* ip, str* iface, int iphdr_incl)
94
-{
95
-	int sock;
96
-	int t;
97
-	union sockaddr_union su;
98
-#if defined (SO_BINDTODEVICE)
99
-	char short_ifname[sizeof(int)];
100
-	int ifname_len;
101
-	char* ifname;
102
-#endif /* SO_BINDTODEVICE */
103
-
104
-	sock = socket(PF_INET, SOCK_RAW, proto);
105
-	if (sock==-1)
106
-		goto error;
107
-	/* set socket options */
108
-	if (iphdr_incl) {
109
-		t=1;
110
-		if (setsockopt(sock, IPPROTO_IP, IP_HDRINCL, &t, sizeof(t))<0){
111
-			ERR("raw_socket: setsockopt(IP_HDRINCL) failed: %s [%d]\n",
112
-					strerror(errno), errno);
113
-			goto error;
114
-		}
115
-	} else {
116
-		/* IP_PKTINFO makes no sense if the ip header is included */
117
-		/* using IP_PKTINFO */
118
-		t=1;
119
-#ifdef IP_PKTINFO
120
-		if (setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &t, sizeof(t))<0){
121
-			ERR("raw_socket: setsockopt(IP_PKTINFO) failed: %s [%d]\n",
122
-					strerror(errno), errno);
123
-			goto error;
124
-		}
125
-#elif defined(IP_RECVDSTADDR)
126
-		if (setsockopt(sock, IPPROTO_IP, IP_RECVDSTADDR, &t, sizeof(t))<0){
127
-			ERR("raw_socket: setsockop(IP_RECVDSTADDR) failed: %s [%d]\n",
128
-					strerror(errno), errno);
129
-			goto error;
130
-		}
131
-#else
132
-#error "no method of getting the destination ip address supported"
133
-#endif /* IP_RECVDSTADDR / IP_PKTINFO */
134
-	}
135
-#if defined (IP_MTU_DISCOVER) && defined (IP_PMTUDISC_DONT)
136
-	t=IP_PMTUDISC_DONT;
137
-	if(setsockopt(sock, IPPROTO_IP, IP_MTU_DISCOVER, &t, sizeof(t)) ==-1){
138
-		ERR("raw_socket: setsockopt(IP_MTU_DISCOVER): %s\n",
139
-				strerror(errno));
140
-		goto error;
141
-	}
142
-#endif /* IP_MTU_DISCOVER && IP_PMTUDISC_DONT */
143
-	if (iface && iface->s){
144
-#if defined (SO_BINDTODEVICE)
145
-		/* workaround for linux bug: arg to setsockopt must have at least
146
-		 * sizeof(int) size or EINVAL would be returned */
147
-		if (iface->len<sizeof(int)){
148
-			memcpy(short_ifname, iface->s, iface->len);
149
-			short_ifname[iface->len]=0; /* make sure it's zero term */
150
-			ifname_len=sizeof(short_ifname);
151
-			ifname=short_ifname;
152
-		}else{
153
-			ifname_len=iface->len;
154
-			ifname=iface->s;
155
-		}
156
-		if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, ifname, ifname_len)
157
-						<0){
158
-				ERR("raw_socket: could not bind to %.*s: %s [%d]\n",
159
-							iface->len, ZSW(iface->s), strerror(errno), errno);
160
-				goto error;
161
-		}
162
-#else /* !SO_BINDTODEVICE */
163
-		/* SO_BINDTODEVICE is linux specific => cannot bind to a device */
164
-		ERR("raw_socket: bind to device supported only on linux\n");
165
-		goto error;
166
-#endif /* SO_BINDTODEVICE */
167
-	}
168
-	/* FIXME: probe_max_receive_buffer(sock) missing */
169
-	if (ip){
170
-		init_su(&su, ip, 0);
171
-		if (bind(sock, &su.s, sockaddru_len(su))==-1){
172
-			ERR("raw_socket: bind(%s) failed: %s [%d]\n",
173
-				ip_addr2a(ip), strerror(errno), errno);
174
-			goto error;
175
-		}
176
-	}
177
-	return sock;
178
-error:
179
-	if (sock!=-1) close(sock);
180
-	return -1;
181
-}
182
-
183
-
184
-
185
-/** create and return an udp over ipv4  raw socket.
186
- * @param ip - if not null the socket will be bound on this ip.
187
- * @param iface - if not null the socket will be bound to this interface
188
- *                (SO_BINDTODEVICE).
189
- * @param iphdr_incl - set to 1 if packets send on this socket include
190
- *                     a pre-built ip header (some fields, like the checksum
191
- *                     will still be filled by the kernel, OTOH packet
192
- *                     fragmentation has to be done in user space).
193
- * @return socket on success, -1 on error
194
- */
195
-int raw_udp4_socket(struct ip_addr* ip, str* iface, int iphdr_incl)
196
-{
197
-	return raw_socket(IPPROTO_UDP, ip, iface, iphdr_incl);
198
-}
199
-
200
-
201
-
202
-/** receives an ipv4 packet using a raw socket.
203
- * An ipv4 packet is received in buf, using IP_PKTINFO or IP_RECVDSTADDR.
204
- * from and to are filled (only the ip part the ports are 0 since this
205
- * function doesn't try to look beyond the IP level).
206
- * @param sock - raw socket
207
- * @param buf - detination buffer.
208
- * @param len - buffer len (should be enough for receiving a packet +
209
- *               IP header).
210
- * @param from - result parameter, the IP address part of it will be filled
211
- *                with the source address and the port with 0.
212
- * @param to - result parameter, the IP address part of it will be filled
213
- *                with the destination (local) address and the port with 0.
214
- * @return packet len or <0 on error: -1 (check errno),
215
- *        -2 no IP_PKTINFO/IP_RECVDSTADDR found or AF mismatch
216
- */
217
-int recvpkt4(int sock, char* buf, int len, union sockaddr_union* from,
218
-					union sockaddr_union* to)
219
-{
220
-	struct iovec iov[1];
221
-	struct msghdr rcv_msg;
222
-	struct cmsghdr* cmsg;
223
-#ifdef IP_PKTINFO
224
-	struct in_pktinfo* rcv_pktinfo;
225
-#endif /* IP_PKTINFO */
226
-	int n, ret;
227
-	char msg_ctrl_buf[1024];
228
-
229
-	iov[0].iov_base=buf;
230
-	iov[0].iov_len=len;
231
-	rcv_msg.msg_name=from;
232
-	rcv_msg.msg_namelen=sockaddru_len(*from);
233
-	rcv_msg.msg_control=msg_ctrl_buf;
234
-	rcv_msg.msg_controllen=sizeof(msg_ctrl_buf);
235
-	rcv_msg.msg_iov=&iov[0];
236
-	rcv_msg.msg_iovlen=1;
237
-	ret=-2; /* no PKT_INFO or AF mismatch */
238
-retry:
239
-	n=recvmsg(sock, &rcv_msg, MSG_WAITALL);
240
-	if (unlikely(n==-1)){
241
-		if (errno==EINTR)
242
-			goto retry;
243
-		ret=n;
244
-		goto end;
245
-	}
246
-	/* find the pkt info */
247
-	for (cmsg=CMSG_FIRSTHDR(&rcv_msg); cmsg; cmsg=CMSG_NXTHDR(&rcv_msg, cmsg)){
248
-#ifdef IP_PKTINFO
249
-		if (likely((cmsg->cmsg_level==IPPROTO_IP) &&
250
-					(cmsg->cmsg_type==IP_PKTINFO))) {
251
-			rcv_pktinfo=(struct in_pktinfo*)CMSG_DATA(cmsg);
252
-			to->sin.sin_family=AF_INET;
253
-			memcpy(&to->sin.sin_addr, &rcv_pktinfo->ipi_spec_dst.s_addr, 
254
-									sizeof(to->sin.sin_addr));
255
-			to->sin.sin_port=0; /* not known */
256
-			/* interface no. in ipi_ifindex */
257
-			ret=n; /* success */
258
-			break;
259
-		}
260
-#elif defined (IP_RECVDSTADDR)
261
-		if (likely((cmsg->cmsg_level==IPPROTO_IP) &&
262
-					(cmsg->cmsg_type==IP_RECVDSTADDR))) {
263
-			to->sin.sin_family=AF_INET;
264
-			memcpy(&to->sin.sin_addr, CMSG_DATA(cmsg),
265
-									sizeof(to->sin.sin_addr));
266
-			to->sin.sin_port=0; /* not known */
267
-			ret=n; /* success */
268
-			break;
269
-		}
270
-#else
271
-#error "no method of getting the destination ip address supported"
272
-#endif /* IP_PKTINFO / IP_RECVDSTADDR */
273
-	}
274
-end:
275
-	return ret;
276
-}
277
-
278
-
279
-
280
-/* receive an ipv4 udp packet over a raw socket.
281
- * The packet is copied in *buf and *buf is advanced to point to the
282
- * payload.  Fills from and to.
283
- * @param rsock - raw socket
284
- * @param buf - the packet will be written to where *buf points intially and
285
- *              then *buf will be advanced to point to the udp payload.
286
- * @param len - buffer length (should be enough to hold at least the
287
- *               ip and udp headers + 1 byte).
288
- * @param from - result parameter, filled with source address and port of the
289
- *               packet.
290
- * @param from - result parameter, filled with destination (local) address and
291
- *               port of the packet.
292
- * @param rf   - filter used to decide whether or not the packet is
293
- *                accepted/processed. If null, all the packets are accepted.
294
- * @return packet len or  <0 on error (-1 and -2 on recv error @see recvpkt4,
295
- *         -3 if the headers are invalid and -4 if the packet doesn't
296
- *         match the  filter).
297
- */
298
-int raw_udp4_recv(int rsock, char** buf, int len, union sockaddr_union* from,
299
-					union sockaddr_union* to, struct raw_filter* rf)
300
-{
301
-	int n;
302
-	unsigned short dst_port;
303
-	unsigned short src_port;
304
-	struct ip_addr dst_ip;
305
-	char* end;
306
-	char* udph_start;
307
-	char* udp_payload;
308
-	struct ip iph;
309
-	struct udphdr udph;
310
-	unsigned short udp_len;
311
-
312
-	n=recvpkt4(rsock, *buf, len, from, to);
313
-	if (unlikely(n<0)) goto error;
314
-	
315
-	end=*buf+n;
316
-	if (unlikely(n<((sizeof(struct ip) * raw_ipip ? 2 : 1)+sizeof(struct udphdr)))) {
317
-		n=-3;
318
-		goto error;
319
-	}
320
-	
321
-	if(raw_ipip) 
322
-        	*buf = *buf + sizeof(struct ip);
323
-	
324
-	/* FIXME: if initial buffer is aligned, one could skip the memcpy
325
-	   and directly cast ip and udphdr pointer to the memory */
326
-	memcpy(&iph, *buf, sizeof(struct ip));
327
-	udph_start=*buf+iph.ip_hl*4;
328
-	udp_payload=udph_start+sizeof(struct udphdr);
329
-	if (unlikely(udp_payload>end)){
330
-		n=-3;
331
-		goto error;
332
-	}
333
-	memcpy(&udph, udph_start, sizeof(struct udphdr));
334
-	udp_len=ntohs(udph.uh_ulen);
335
-	if (unlikely((udph_start+udp_len)!=end)){
336
-		if ((udph_start+udp_len)>end){
337
-			n=-3;
338
-			goto error;
339
-		}else{
340
-			ERR("udp length too small: %d/%d\n",
341
-					(int)udp_len, (int)(end-udph_start));
342
-			n=-3;
343
-			goto error;
344
-		}
345
-	}
346
-	/* advance buf */
347
-	*buf=udp_payload;
348
-	n=(int)(end-*buf);
349
-	/* fill ip from the packet (needed if no PKT_INFO is used) */
350
-	dst_ip.af=AF_INET;
351
-	dst_ip.len=4;
352
-	dst_ip.u.addr32[0]=iph.ip_dst.s_addr;
353
-	/* fill dst_port */
354
-	dst_port=ntohs(udph.uh_dport);
355
-	ip_addr2su(to, &dst_ip, dst_port);
356
-	/* fill src_port */
357
-	src_port=ntohs(udph.uh_sport);
358
-	su_setport(from, src_port);
359
-	if (likely(rf)) {
360
-		su2ip_addr(&dst_ip, to);
361
-		if ( (dst_port && rf->port1 && ((dst_port<rf->port1) ||
362
-										(dst_port>rf->port2)) ) ||
363
-			(matchnet(&dst_ip, &rf->dst)!=1) ){
364
-			/* no match */
365
-			n=-4;
366
-			goto error;
367
-		}
368
-	}
369
-	
370
-error:
371
-	return n;
372
-}
373
-
374
-
375
-
376
-/** udp checksum helper: compute the pseudo-header 16-bit "sum".
377
- * Computes the partial checksum (no complement) of the pseudo-header.
378
- * It is meant to be used by udpv4_chksum().
379
- * @param uh - filled udp header
380
- * @param src - source ip address in network byte order.
381
- * @param dst - destination ip address in network byte order.
382
- * @param length - payload length (not including the udp header),
383
- *                 in _host_ order.
384
- * @return the partial checksum in host order
385
- */
386
-static inline unsigned short udpv4_vhdr_sum(	struct udphdr* uh,
387
-										struct in_addr* src,
388
-										struct in_addr* dst,
389
-										unsigned short length)
390
-{
391
-	unsigned sum;
392
-	
393
-	/* pseudo header */
394
-	sum=(src->s_addr>>16)+(src->s_addr&0xffff)+
395
-		(dst->s_addr>>16)+(dst->s_addr&0xffff)+
396
-		htons(IPPROTO_UDP)+(uh->uh_ulen);
397
-	/* udp header */
398
-	sum+=(uh->uh_dport)+(uh->uh_sport)+(uh->uh_ulen) + 0 /*chksum*/; 
399
-	/* fold it */
400
-	sum=(sum>>16)+(sum&0xffff);
401
-	sum+=(sum>>16);
402
-	/* no complement */
403
-	return ntohs((unsigned short) sum);
404
-}
405
-
406
-
407
-
408
-/** compute the udp over ipv4 checksum.
409
- * @param u - filled udp header (except checksum).
410
- * @param src - source ip v4 address, in _network_ byte order.
411
- * @param dst - destination ip v4 address, int _network_ byte order.
412
- * @param data - pointer to the udp payload.
413
- * @param length - payload length, not including the udp header and in
414
- *                 _host_ order. The length mist be <= 0xffff - 8
415
- *                 (to allow space for the udp header).
416
- * @return the checksum in _host_ order */
417
-inline static unsigned short udpv4_chksum(struct udphdr* u,
418
-							struct in_addr* src, struct in_addr* dst,
419
-							unsigned char* data, unsigned short length)
420
-{
421
-	unsigned sum;
422
-	unsigned char* end;
423
-	sum=udpv4_vhdr_sum(u, src, dst, length);
424
-	end=data+(length&(~0x1)); /* make sure it's even */
425
-	/* TODO: 16 & 32 bit aligned version */
426
-		/* not aligned */
427
-		for(;data<end;data+=2){
428
-			sum+=((data[0]<<8)+data[1]);
429
-		}
430
-		if (length&0x1)
431
-			sum+=((*data)<<8);
432
-	
433
-	/* fold it */
434
-	sum=(sum>>16)+(sum&0xffff);
435
-	sum+=(sum>>16);
436
-	return (unsigned short)~sum;
437
-}
438
-
439
-
440
-
441
-/** fill in an udp header.
442
- * @param u - udp header that will be filled.
443
- * @param from - source ip v4 address and port.
444
- * @param to -   destination ip v4 address and port.
445
- * @param buf - pointer to the payload.
446
- * @param len - payload length (not including the udp header).
447
- * @param do_chk - if set the udp checksum will be computed, else it will
448
- *                 be set to 0.
449
- * @return 0 on success, < 0 on error.
450
- */
451
-inline static int mk_udp_hdr(struct udphdr* u, struct sockaddr_in* from, 
452
-				struct sockaddr_in* to, unsigned char* buf, int len,
453
-					int do_chk)
454
-{
455
-	u->uh_ulen=htons((unsigned short)len+sizeof(struct udphdr));
456
-	u->uh_sport=from->sin_port;
457
-	u->uh_dport=to->sin_port;
458
-	if (do_chk)
459
-		u->uh_sum=htons(
460
-				udpv4_chksum(u, &from->sin_addr, &to->sin_addr,  buf, len));
461
-	else
462
-		u->uh_sum=0; /* no checksum */
463
-	return 0;
464
-}
465
-
466
-
467
-
468
-/** fill in an ip header.
469
- * Note: the checksum is _not_ computed.
470
- * WARNING: The ip header length and offset might be filled in
471
- * _host_ byte order or network byte order (depending on the OS, for example
472
- *  freebsd needs host byte order for raw sockets with IPHDR_INC, while
473
- *  linux needs network byte order).
474
- * @param iph - ip header that will be filled.
475
- * @param from - source ip v4 address (network byte order).
476
- * @param to -   destination ip v4 address (network byte order).
477
- * @param payload len - payload length (not including the ip header).
478
- * @param proto - protocol.
479
- * @return 0 on success, < 0 on error.
480
- */
481
-inline static int mk_ip_hdr(struct ip* iph, struct in_addr* from,
482
-				struct in_addr* to, int payload_len, unsigned char proto)
483
-{
484
-	iph->ip_hl = sizeof(struct ip)/4;
485
-	iph->ip_v = 4;
486
-	iph->ip_tos = tos;
487
-	/* on freebsd ip_len _must_ be in _host_ byte order instead
488
-	   of network byte order. On linux the length is ignored (it's filled
489
-	   automatically every time). */
490
-	iph->ip_len = RAW_IPHDR_IP_LEN(payload_len + sizeof(struct ip));
491
-	iph->ip_id = 0; /* 0 => will be filled automatically by the kernel */
492
-	iph->ip_off = 0; /* frag.: first 3 bits=flags=0, last 13 bits=offset */
493
-	iph->ip_ttl = cfg_get(core, core_cfg, udp4_raw_ttl);
494
-	iph->ip_p = proto;
495
-	iph->ip_src = *from;
496
-	iph->ip_dst = *to;
497
-	iph->ip_sum = 0;
498
-
499
-	return 0;
500
-}
501
-
502
-
503
-
504
-/** send an udp packet over a non-ip_hdrincl raw socket.
505
- * @param rsock - raw socket
506
- * @param buf - data
507
- * @param len - data len
508
- * @param from - source address:port (_must_ be non-null, but the ip address
509
- *                can be 0, in which case it will be filled by the kernel).
510
- * @param to - destination address:port
511
- * @return  <0 on error (errno set too), number of bytes sent on success
512
- *          (including the udp header => on success len + udpheader size).
513
- */
514
-int raw_udp4_send(int rsock, char* buf, unsigned int len,
515
-					union sockaddr_union* from,
516
-					union sockaddr_union* to)
517
-{
518
-	struct msghdr snd_msg;
519
-	struct cmsghdr* cmsg;
520
-#ifdef IP_PKTINFO
521
-	struct in_pktinfo* snd_pktinfo;
522
-#endif /* IP_PKTINFO */
523
-	struct iovec iov[2];
524
-	struct udphdr udp_hdr;
525
-	char msg_ctrl_snd_buf[1024];
526
-	int ret;
527
-
528
-	memset(&snd_msg, 0, sizeof(snd_msg));
529
-	snd_msg.msg_name=&to->sin;
530
-	snd_msg.msg_namelen=sockaddru_len(*to);
531
-	snd_msg.msg_iov=&iov[0];
532
-	/* prepare udp header */
533
-	mk_udp_hdr(&udp_hdr, &from->sin, &to->sin, (unsigned char*)buf, len, 1);
534
-	iov[0].iov_base=(char*)&udp_hdr;
535
-	iov[0].iov_len=sizeof(udp_hdr);
536
-	iov[1].iov_base=buf;
537
-	iov[1].iov_len=len;
538
-	snd_msg.msg_iovlen=2;
539
-	snd_msg.msg_control=msg_ctrl_snd_buf;
540
-	snd_msg.msg_controllen=sizeof(msg_ctrl_snd_buf);
541
-	/* init pktinfo cmsg */
542
-	cmsg=CMSG_FIRSTHDR(&snd_msg);
543
-	cmsg->cmsg_level=IPPROTO_IP;
544
-#ifdef IP_PKTINFO
545
-	cmsg->cmsg_type=IP_PKTINFO;
546
-	cmsg->cmsg_len=CMSG_LEN(sizeof(struct in_pktinfo));
547
-	snd_pktinfo=(struct in_pktinfo*)CMSG_DATA(cmsg);
548
-	snd_pktinfo->ipi_ifindex=0;
549
-	snd_pktinfo->ipi_spec_dst.s_addr=from->sin.sin_addr.s_addr;
550
-#elif defined (IP_SENDSRCADDR)
551
-	cmsg->cmsg_type=IP_SENDSRCADDR;
552
-	cmsg->cmsg_len=CMSG_LEN(sizeof(struct in_addr));
553
-	memcpy(CMSG_DATA(cmsg), &from->sin.sin_addr.s_addr,
554
-							sizeof(struct in_addr));
555
-#else
556
-#error "no method of setting the source ip supported"
557
-#endif /* IP_PKTINFO / IP_SENDSRCADDR */
558
-	snd_msg.msg_controllen=cmsg->cmsg_len;
559
-	snd_msg.msg_flags=0;
560
-	ret=sendmsg(rsock, &snd_msg, 0);
561
-	return ret;
562
-}
563
-
564
-
565
-
566
-/** send an udp packet over an IP_HDRINCL raw socket.
567
- * If needed, send several fragments.
568
- * @param rsock - raw socket
569
- * @param buf - data
570
- * @param len - data len
571
- * @param from - source address:port (_must_ be non-null, but the ip address
572
- *                can be 0, in which case it will be filled by the kernel).
573
- * @param to - destination address:port
574
- * @param mtu - maximum datagram size (including the ip header, excluding
575
- *              link layer headers). Minimum allowed size is 28
576
- *               (sizeof(ip_header + udp_header)). If mtu is lower, it will
577
- *               be ignored (the packet will be sent un-fragmented).
578
- *              0 can be used to disable fragmentation.
579
- * @return  <0 on error (-2: datagram too big, -1: check errno),
580
- *          number of bytes sent on success
581
- *          (including the ip & udp headers =>
582
- *               on success len + udpheader + ipheader size).
583
- */
584
-int raw_iphdr_udp4_send(int rsock, char* buf, unsigned int len,
585
-						union sockaddr_union* from,
586
-						union sockaddr_union* to, unsigned short mtu)
587
-{
588
-	struct msghdr snd_msg;
589
-	struct iovec iov[2];
590
-	struct ip_udp_hdr {
591
-		struct ip ip;
592
-		struct udphdr udp;
593
-	} hdr;
594
-	unsigned int totlen;
595
-#ifndef RAW_IPHDR_INC_AUTO_FRAG
596
-	unsigned int ip_frag_size; /* fragment size */
597
-	unsigned int last_frag_extra; /* extra bytes possible in the last frag */
598
-	unsigned int ip_payload;
599
-	unsigned int last_frag_offs;
600
-	void* last_frag_start;
601
-	int frg_no;
602
-#endif /* RAW_IPHDR_INC_AUTO_FRAG */
603
-	int ret;
604
-
605
-	totlen = len + sizeof(hdr);
606
-	if (unlikely(totlen) > 65535)
607
-		return -2;
608
-	memset(&snd_msg, 0, sizeof(snd_msg));
609
-	snd_msg.msg_name=&to->sin;
610
-	snd_msg.msg_namelen=sockaddru_len(*to);
611
-	snd_msg.msg_iov=&iov[0];
612
-	/* prepare the udp & ip headers */
613
-	mk_udp_hdr(&hdr.udp, &from->sin, &to->sin, (unsigned char*)buf, len, 1);
614
-	mk_ip_hdr(&hdr.ip, &from->sin.sin_addr, &to->sin.sin_addr,
615
-				len + sizeof(hdr.udp), IPPROTO_UDP);
616
-	iov[0].iov_base=(char*)&hdr;
617
-	iov[0].iov_len=sizeof(hdr);
618
-	snd_msg.msg_iovlen=2;
619
-	snd_msg.msg_control=0;
620
-	snd_msg.msg_controllen=0;
621
-	snd_msg.msg_flags=0;
622
-	/* this part changes for different fragments */
623
-	/* packets are fragmented if mtu has a valid value (at least an
624
-	   IP header + UDP header fit in it) and if the total length is greater
625
-	   then the mtu */
626
-#ifndef RAW_IPHDR_INC_AUTO_FRAG
627
-	if (likely(totlen <= mtu || mtu <= sizeof(hdr))) {
628
-#endif /* RAW_IPHDR_INC_AUTO_FRAG */
629
-		iov[1].iov_base=buf;
630
-		iov[1].iov_len=len;
631
-		ret=sendmsg(rsock, &snd_msg, 0);
632
-#ifndef RAW_IPHDR_INC_AUTO_FRAG
633
-	} else {
634
-		ip_payload = len + sizeof(hdr.udp);
635
-		/* a fragment offset must be a multiple of 8 => its size must
636
-		   also be a multiple of 8, except for the last fragment */
637
-		ip_frag_size = (mtu -sizeof(hdr.ip)) & (~7);
638
-		last_frag_extra = (mtu - sizeof(hdr.ip)) & 7; /* rest */
639
-		frg_no = ip_payload / ip_frag_size +
640
-				 ((ip_payload % ip_frag_size) > last_frag_extra);
641
-		/*ip_last_frag_size = ip_payload % frag_size +
642
-							((ip_payload % frag_size) <= last_frag_extra) *
643
-							ip_frag_size; */
644
-		last_frag_offs = (frg_no - 1) * ip_frag_size;
645
-		/* if we are here mtu => sizeof(ip_h+udp_h) && payload > mtu
646
-		   => last_frag_offs >= sizeof(hdr.udp) */
647
-		last_frag_start = buf + last_frag_offs - sizeof(hdr.udp);
648
-		hdr.ip.ip_id = fastrand_max(65534) + 1; /* random id, should be != 0
649
-											  (if 0 the kernel will fill it) */
650
-		/* send the first fragment */
651
-		iov[1].iov_base=buf;
652
-		/* ip_frag_size >= sizeof(hdr.udp) because we are here only
653
-		   if mtu >= sizeof(hdr.ip) + sizeof(hdr.udp) */
654
-		iov[1].iov_len=ip_frag_size - sizeof(hdr.udp);
655
-		hdr.ip.ip_len = RAW_IPHDR_IP_LEN(ip_frag_size + sizeof(hdr.ip));
656
-		hdr.ip.ip_off = RAW_IPHDR_IP_OFF(0x2000); /* set MF */
657
-		ret=sendmsg(rsock, &snd_msg, 0);
658
-		if (unlikely(ret < 0))
659
-			goto end;
660
-		/* all the other fragments, include only the ip header */
661
-		iov[0].iov_len = sizeof(hdr.ip);
662
-		iov[1].iov_base =  (char*)iov[1].iov_base + iov[1].iov_len;
663
-		/* fragments between the first and the last */
664
-		while(unlikely(iov[1].iov_base < last_frag_start)) {
665
-			iov[1].iov_len = ip_frag_size;
666
-			hdr.ip.ip_len = RAW_IPHDR_IP_LEN(iov[1].iov_len + sizeof(hdr.ip));
667
-			/* set MF  */
668
-			hdr.ip.ip_off = RAW_IPHDR_IP_OFF( (unsigned short)
669
-									(((char*)iov[1].iov_base - (char*)buf +
670
-										sizeof(hdr.udp)) / 8) | 0x2000 );
671
-			ret=sendmsg(rsock, &snd_msg, 0);
672
-			if (unlikely(ret < 0))
673
-				goto end;
674
-			iov[1].iov_base =  (char*)iov[1].iov_base + iov[1].iov_len;
675
-		}
676
-		/* last fragment */
677
-		iov[1].iov_len = buf + len - (char*)iov[1].iov_base;
678
-		hdr.ip.ip_len = RAW_IPHDR_IP_LEN(iov[1].iov_len + sizeof(hdr.ip));
679
-		/* don't set MF (last fragment) */
680
-		hdr.ip.ip_off = RAW_IPHDR_IP_OFF((unsigned short)
681
-									(((char*)iov[1].iov_base - (char*)buf +
682
-										sizeof(hdr.udp)) / 8) );
683
-		ret=sendmsg(rsock, &snd_msg, 0);
684
-		if (unlikely(ret < 0))
685
-			goto end;
686
-	}
687
-end:
688
-#endif /* RAW_IPHDR_INC_AUTO_FRAG */
689
-	return ret;
690
-}
691
-
692
-
693
-
694
-#endif /* USE_RAW_SOCKS */
Browse code

Core Removed history, svn $id$ and doxygen udpates on the .c files

Olle E. Johansson authored on 03/01/2015 09:53:17
Showing 1 changed files
... ...
@@ -1,6 +1,4 @@
1 1
 /* 
2
- * $Id$
3
- *
4 2
  * Copyright (C) 2010 iptelorg GmbH
5 3
  *
6 4
  * Permission to use, copy, modify, and distribute this software for any
... ...
@@ -15,18 +13,12 @@
15 13
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 14
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 15
  */
18
-/** raw socket functions.
16
+
17
+/** Kamailio core :: raw socket functions.
19 18
  *  @file raw_sock.c
20 19
  *  @ingroup core
21 20
  *  Module: @ref core
22 21
  */
23
-/* 
24
- * History:
25
- * --------
26
- *  2010-06-07  initial version (from older code) andrei
27
- *  2010-06-15  IP_HDRINCL raw socket support, including on-send
28
- *               fragmentation (andrei)
29
- */
30 22
 
31 23
 #ifdef USE_RAW_SOCKS
32 24
 
Browse code

core: Fixed inline function declaration for non-gcc linkers

usage of either 'extern inline' or 'static inline' depending on function scope is recommended

Marius Zbihlei authored on 14/09/2012 10:15:47
Showing 1 changed files
... ...
@@ -391,7 +391,7 @@ error:
391 391
  *                 in _host_ order.
392 392
  * @return the partial checksum in host order
393 393
  */
394
-inline unsigned short udpv4_vhdr_sum(	struct udphdr* uh,
394
+static inline unsigned short udpv4_vhdr_sum(	struct udphdr* uh,
395 395
 										struct in_addr* src,
396 396
 										struct in_addr* dst,
397 397
 										unsigned short length)
Browse code

core: new raw_ipip flag, indicate to cut off the extra IP header in IPIP encapsulation.

Alexandr Dubovikov authored on 22/08/2011 11:11:01
Showing 1 changed files
... ...
@@ -84,6 +84,8 @@
84 84
 
85 85
 #endif /* __OS_* */
86 86
 
87
+int raw_ipip = 0; /* set if raw socket is in capture mode for IPIP */
88
+
87 89
 
88 90
 /** create and return a raw socket.
89 91
  * @param proto - protocol used (e.g. IPPROTO_UDP, IPPROTO_RAW)
... ...
@@ -319,10 +321,14 @@ int raw_udp4_recv(int rsock, char** buf, int len, union sockaddr_union* from,
319 321
 	if (unlikely(n<0)) goto error;
320 322
 	
321 323
 	end=*buf+n;
322
-	if (unlikely(n<(sizeof(struct ip)+sizeof(struct udphdr)))) {
324
+	if (unlikely(n<((sizeof(struct ip) * raw_ipip ? 2 : 1)+sizeof(struct udphdr)))) {
323 325
 		n=-3;
324 326
 		goto error;
325 327
 	}
328
+	
329
+	if(raw_ipip) 
330
+        	*buf = *buf + sizeof(struct ip);
331
+	
326 332
 	/* FIXME: if initial buffer is aligned, one could skip the memcpy
327 333
 	   and directly cast ip and udphdr pointer to the memory */
328 334
 	memcpy(&iph, *buf, sizeof(struct ip));
Browse code

raw sockets: freebsd support

Support freebsd and theoretically other BSDs (other BSDs not tested):

- on most BSDs the offset and length of the ip header must be
filled in host byte order (when using raw sockets with
IPHDR_INC).
- no need for user-space fragmentation for raw sockets
- use IP_RECVDSTADDR and IPSENDSRCADDR instead of IP_PKTINFO
(for raw sockets without IPHDR_INC)
- fix ip header length (wrongly computed, on linux it worked
because linux always ignores and overwrites it)

Andrei Pelinescu-Onciul authored on 10/08/2010 15:43:25
Showing 1 changed files
... ...
@@ -27,9 +27,6 @@
27 27
  *  2010-06-15  IP_HDRINCL raw socket support, including on-send
28 28
  *               fragmentation (andrei)
29 29
  */
30
-/*
31
- * FIXME: IP_PKTINFO & IP_HDRINCL - linux specific
32
- */
33 30
 
34 31
 #ifdef USE_RAW_SOCKS
35 32
 
... ...
@@ -47,6 +44,7 @@
47 44
 #include <fcntl.h>
48 45
 #include <sys/socket.h>
49 46
 #include <netinet/in.h>
47
+#include <netinet/in_systm.h>
50 48
 #include <arpa/inet.h>
51 49
 #ifndef __USE_BSD
52 50
 #define __USE_BSD  /* on linux use bsd version of iphdr (more portable) */
... ...
@@ -60,11 +58,38 @@
60 58
 #include "cfg_core.h"
61 59
 
62 60
 
61
+#if defined (__OS_freebsd) || defined (__OS_netbsd) || defined(__OS_openbsd) \
62
+	|| defined (__OS_darwin)
63
+/** fragmentation is done by the kernel (no need to do it in userspace) */
64
+#define RAW_IPHDR_INC_AUTO_FRAG
65
+#endif /* __OS_* */
66
+
67
+/* macros for converting values in the expected format */
68
+#if defined (__OS_freebsd) || defined (__OS_netbsd) || defined (__OS_darwin)
69
+/* on freebsd and netbsd the ip offset (along with flags) and the
70
+   ip header length must be filled in _host_ bytes order format.
71
+   The same is true for openbsd < 2.1.
72
+*/
73
+/** convert the ip offset in the format expected by the kernel. */
74
+#define RAW_IPHDR_IP_OFF(off) (unsigned short)(off)
75
+/** convert the ip total length in the format expected by the kernel. */
76
+#define RAW_IPHDR_IP_LEN(tlen) (unsigned short)(tlen)
77
+
78
+#else /* __OS_* */
79
+/* linux, openbsd >= 2.1 a.s.o. */
80
+/** convert the ip offset in the format expected by the kernel. */
81
+#define RAW_IPHDR_IP_OFF(off)  htons((unsigned short)(off))
82
+/** convert the ip total length in the format expected by the kernel. */
83
+#define RAW_IPHDR_IP_LEN(tlen) htons((unsigned short)(tlen))
84
+
85
+#endif /* __OS_* */
86
+
87
+
63 88
 /** create and return a raw socket.
64 89
  * @param proto - protocol used (e.g. IPPROTO_UDP, IPPROTO_RAW)
65 90
  * @param ip - if not null the socket will be bound on this ip.
66 91
  * @param iface - if not null the socket will be bound to this interface
67
- *                (SO_BINDTODEVICE).
92
+ *                (SO_BINDTODEVICE). This is supported only on linux.
68 93
  * @param iphdr_incl - set to 1 if packets send on this socket include
69 94
  *                     a pre-built ip header (some fields, like the checksum
70 95
  *                     will still be filled by the kernel, OTOH packet
... ...
@@ -76,9 +101,11 @@ int raw_socket(int proto, struct ip_addr* ip, str* iface, int iphdr_incl)
76 101
 	int sock;
77 102
 	int t;
78 103
 	union sockaddr_union su;
104
+#if defined (SO_BINDTODEVICE)
79 105
 	char short_ifname[sizeof(int)];
80 106
 	int ifname_len;
81 107
 	char* ifname;
108
+#endif /* SO_BINDTODEVICE */
82 109
 
83 110
 	sock = socket(PF_INET, SOCK_RAW, proto);
84 111
 	if (sock==-1)
... ...
@@ -95,19 +122,32 @@ int raw_socket(int proto, struct ip_addr* ip, str* iface, int iphdr_incl)
95 122
 		/* IP_PKTINFO makes no sense if the ip header is included */
96 123
 		/* using IP_PKTINFO */
97 124
 		t=1;
125
+#ifdef IP_PKTINFO
98 126
 		if (setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &t, sizeof(t))<0){
99 127
 			ERR("raw_socket: setsockopt(IP_PKTINFO) failed: %s [%d]\n",
100 128
 					strerror(errno), errno);
101 129
 			goto error;
102 130
 		}
131
+#elif defined(IP_RECVDSTADDR)
132
+		if (setsockopt(sock, IPPROTO_IP, IP_RECVDSTADDR, &t, sizeof(t))<0){
133
+			ERR("raw_socket: setsockop(IP_RECVDSTADDR) failed: %s [%d]\n",
134
+					strerror(errno), errno);
135
+			goto error;
136
+		}
137
+#else
138
+#error "no method of getting the destination ip address supported"
139
+#endif /* IP_RECVDSTADDR / IP_PKTINFO */
103 140
 	}
141
+#if defined (IP_MTU_DISCOVER) && defined (IP_PMTUDISC_DONT)
104 142
 	t=IP_PMTUDISC_DONT;
105 143
 	if(setsockopt(sock, IPPROTO_IP, IP_MTU_DISCOVER, &t, sizeof(t)) ==-1){
106 144
 		ERR("raw_socket: setsockopt(IP_MTU_DISCOVER): %s\n",
107 145
 				strerror(errno));
108 146
 		goto error;
109 147
 	}
148
+#endif /* IP_MTU_DISCOVER && IP_PMTUDISC_DONT */
110 149
 	if (iface && iface->s){
150
+#if defined (SO_BINDTODEVICE)
111 151
 		/* workaround for linux bug: arg to setsockopt must have at least
112 152
 		 * sizeof(int) size or EINVAL would be returned */
113 153
 		if (iface->len<sizeof(int)){
... ...
@@ -125,6 +165,11 @@ int raw_socket(int proto, struct ip_addr* ip, str* iface, int iphdr_incl)
125 165
 							iface->len, ZSW(iface->s), strerror(errno), errno);
126 166
 				goto error;
127 167
 		}
168
+#else /* !SO_BINDTODEVICE */
169
+		/* SO_BINDTODEVICE is linux specific => cannot bind to a device */
170
+		ERR("raw_socket: bind to device supported only on linux\n");
171
+		goto error;
172
+#endif /* SO_BINDTODEVICE */
128 173
 	}
129 174
 	/* FIXME: probe_max_receive_buffer(sock) missing */
130 175
 	if (ip){
... ...
@@ -160,8 +205,8 @@ int raw_udp4_socket(struct ip_addr* ip, str* iface, int iphdr_incl)
160 205
 
161 206
 
162 207
 
163
-/** receives an ipv4 packet suing a raw socket.
164
- * An ipv4 packet is received in buf, using IP_PKTINFO.
208
+/** receives an ipv4 packet using a raw socket.
209
+ * An ipv4 packet is received in buf, using IP_PKTINFO or IP_RECVDSTADDR.
165 210
  * from and to are filled (only the ip part the ports are 0 since this
166 211
  * function doesn't try to look beyond the IP level).
167 212
  * @param sock - raw socket
... ...
@@ -173,7 +218,7 @@ int raw_udp4_socket(struct ip_addr* ip, str* iface, int iphdr_incl)
173 218
  * @param to - result parameter, the IP address part of it will be filled
174 219
  *                with the destination (local) address and the port with 0.
175 220
  * @return packet len or <0 on error: -1 (check errno),
176
- *        -2 no IP_PKTINFO found or AF mismatch
221
+ *        -2 no IP_PKTINFO/IP_RECVDSTADDR found or AF mismatch
177 222
  */
178 223
 int recvpkt4(int sock, char* buf, int len, union sockaddr_union* from,
179 224
 					union sockaddr_union* to)
... ...
@@ -181,7 +226,9 @@ int recvpkt4(int sock, char* buf, int len, union sockaddr_union* from,
181 226
 	struct iovec iov[1];
182 227
 	struct msghdr rcv_msg;
183 228
 	struct cmsghdr* cmsg;
229
+#ifdef IP_PKTINFO
184 230
 	struct in_pktinfo* rcv_pktinfo;
231
+#endif /* IP_PKTINFO */
185 232
 	int n, ret;
<