This source file includes following definitions.
- rip_init
- rip_input
- rip_output
- rip_ctloutput
- rip_usrreq
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71 #include <sys/param.h>
72 #include <sys/systm.h>
73 #include <sys/mbuf.h>
74 #include <sys/socket.h>
75 #include <sys/protosw.h>
76 #include <sys/socketvar.h>
77
78 #include <net/if.h>
79 #include <net/route.h>
80
81 #include <netinet/in.h>
82 #include <netinet/in_systm.h>
83 #include <netinet/ip.h>
84 #include <netinet/ip_mroute.h>
85 #include <netinet/ip_var.h>
86 #include <netinet/in_pcb.h>
87 #include <netinet/in_var.h>
88 #include <netinet/ip_icmp.h>
89
90 struct inpcbtable rawcbtable;
91
92
93
94
95 #define RIPSNDQ 8192
96 #define RIPRCVQ 8192
97
98
99
100
101
102
103
104
105 void
106 rip_init()
107 {
108
109 in_pcbinit(&rawcbtable, 1);
110 }
111
112 struct sockaddr_in ripsrc = { sizeof(ripsrc), AF_INET };
113
114
115
116
117
118
119 void
120 rip_input(struct mbuf *m, ...)
121 {
122 struct ip *ip = mtod(m, struct ip *);
123 struct inpcb *inp, *last = NULL;
124 struct mbuf *opts = NULL;
125
126 ripsrc.sin_addr = ip->ip_src;
127 CIRCLEQ_FOREACH(inp, &rawcbtable.inpt_queue, inp_queue) {
128 #ifdef INET6
129 if (inp->inp_flags & INP_IPV6)
130 continue;
131 #endif
132 if (inp->inp_ip.ip_p && inp->inp_ip.ip_p != ip->ip_p)
133 continue;
134 if (inp->inp_laddr.s_addr &&
135 inp->inp_laddr.s_addr != ip->ip_dst.s_addr)
136 continue;
137 if (inp->inp_faddr.s_addr &&
138 inp->inp_faddr.s_addr != ip->ip_src.s_addr)
139 continue;
140 if (last) {
141 struct mbuf *n;
142
143 if ((n = m_copy(m, 0, (int)M_COPYALL)) != NULL) {
144 if (last->inp_flags & INP_CONTROLOPTS)
145 ip_savecontrol(last, &opts, ip, n);
146 if (sbappendaddr(&last->inp_socket->so_rcv,
147 sintosa(&ripsrc), n, opts) == 0) {
148
149 m_freem(n);
150 if (opts)
151 m_freem(opts);
152 } else
153 sorwakeup(last->inp_socket);
154 opts = NULL;
155 }
156 }
157 last = inp;
158 }
159 if (last) {
160 if (last->inp_flags & INP_CONTROLOPTS)
161 ip_savecontrol(last, &opts, ip, m);
162 if (sbappendaddr(&last->inp_socket->so_rcv, sintosa(&ripsrc), m,
163 opts) == 0) {
164 m_freem(m);
165 if (opts)
166 m_freem(opts);
167 } else
168 sorwakeup(last->inp_socket);
169 } else {
170 if (ip->ip_p != IPPROTO_ICMP)
171 icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PROTOCOL, 0, 0);
172 else
173 m_freem(m);
174 ipstat.ips_noproto++;
175 ipstat.ips_delivered--;
176 }
177 }
178
179
180
181
182
183 int
184 rip_output(struct mbuf *m, ...)
185 {
186 struct socket *so;
187 u_long dst;
188 struct ip *ip;
189 struct inpcb *inp;
190 int flags;
191 va_list ap;
192
193 va_start(ap, m);
194 so = va_arg(ap, struct socket *);
195 dst = va_arg(ap, u_long);
196 va_end(ap);
197
198 inp = sotoinpcb(so);
199 flags = (so->so_options & (SO_DONTROUTE|SO_JUMBO)) | IP_ALLOWBROADCAST;
200
201
202
203
204
205 if ((inp->inp_flags & INP_HDRINCL) == 0) {
206 if ((m->m_pkthdr.len + sizeof(struct ip)) > IP_MAXPACKET) {
207 m_freem(m);
208 return (EMSGSIZE);
209 }
210 M_PREPEND(m, sizeof(struct ip), M_DONTWAIT);
211 if (!m)
212 return (ENOBUFS);
213 ip = mtod(m, struct ip *);
214 ip->ip_tos = inp->inp_ip.ip_tos;
215 ip->ip_off = htons(0);
216 ip->ip_p = inp->inp_ip.ip_p;
217 ip->ip_len = htons(m->m_pkthdr.len);
218 ip->ip_src = inp->inp_laddr;
219 ip->ip_dst.s_addr = dst;
220 ip->ip_ttl = inp->inp_ip.ip_ttl ? inp->inp_ip.ip_ttl : MAXTTL;
221 } else {
222 if (m->m_pkthdr.len > IP_MAXPACKET) {
223 m_freem(m);
224 return (EMSGSIZE);
225 }
226 if (m->m_pkthdr.len < sizeof(struct ip)) {
227 m_freem(m);
228 return (EINVAL);
229 }
230 ip = mtod(m, struct ip *);
231
232
233
234
235 if ((ip->ip_hl != (sizeof (*ip) >> 2) && inp->inp_options) ||
236 ntohs(ip->ip_len) > m->m_pkthdr.len ||
237 ntohs(ip->ip_len) < ip->ip_hl << 2) {
238 m_freem(m);
239 return (EINVAL);
240 }
241 if (ip->ip_id == 0) {
242 ip->ip_id = htons(ip_randomid());
243 }
244
245 flags |= IP_RAWOUTPUT;
246 ipstat.ips_rawout++;
247 }
248 #ifdef INET6
249
250
251
252
253
254 #endif
255 return (ip_output(m, inp->inp_options, &inp->inp_route, flags,
256 inp->inp_moptions, inp));
257 }
258
259
260
261
262 int
263 rip_ctloutput(int op, struct socket *so, int level, int optname,
264 struct mbuf **m)
265 {
266 struct inpcb *inp = sotoinpcb(so);
267 int error;
268
269 if (level != IPPROTO_IP) {
270 if (op == PRCO_SETOPT && *m)
271 (void) m_free(*m);
272 return (EINVAL);
273 }
274
275 switch (optname) {
276
277 case IP_HDRINCL:
278 error = 0;
279 if (op == PRCO_SETOPT) {
280 if (*m == 0 || (*m)->m_len < sizeof (int))
281 error = EINVAL;
282 else if (*mtod(*m, int *))
283 inp->inp_flags |= INP_HDRINCL;
284 else
285 inp->inp_flags &= ~INP_HDRINCL;
286 if (*m)
287 (void)m_free(*m);
288 } else {
289 *m = m_get(M_WAIT, M_SOOPTS);
290 (*m)->m_len = sizeof(int);
291 *mtod(*m, int *) = inp->inp_flags & INP_HDRINCL;
292 }
293 return (error);
294
295 case MRT_INIT:
296 case MRT_DONE:
297 case MRT_ADD_VIF:
298 case MRT_DEL_VIF:
299 case MRT_ADD_MFC:
300 case MRT_DEL_MFC:
301 case MRT_VERSION:
302 case MRT_ASSERT:
303 case MRT_API_SUPPORT:
304 case MRT_API_CONFIG:
305 case MRT_ADD_BW_UPCALL:
306 case MRT_DEL_BW_UPCALL:
307 #ifdef MROUTING
308 switch (op) {
309 case PRCO_SETOPT:
310 error = ip_mrouter_set(so, optname, m);
311 break;
312 case PRCO_GETOPT:
313 error = ip_mrouter_get(so, optname, m);
314 break;
315 default:
316 error = EINVAL;
317 break;
318 }
319 return (error);
320 #else
321 if (op == PRCO_SETOPT && *m)
322 m_free(*m);
323 return (EOPNOTSUPP);
324 #endif
325 }
326 return (ip_ctloutput(op, so, level, optname, m));
327 }
328
329 u_long rip_sendspace = RIPSNDQ;
330 u_long rip_recvspace = RIPRCVQ;
331
332
333 int
334 rip_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam,
335 struct mbuf *control)
336 {
337 int error = 0;
338 struct inpcb *inp = sotoinpcb(so);
339 #ifdef MROUTING
340 extern struct socket *ip_mrouter;
341 #endif
342 if (req == PRU_CONTROL)
343 return (in_control(so, (u_long)m, (caddr_t)nam,
344 (struct ifnet *)control));
345
346 if (inp == NULL && req != PRU_ATTACH) {
347 error = EINVAL;
348 goto release;
349 }
350
351 switch (req) {
352
353 case PRU_ATTACH:
354 if (inp)
355 panic("rip_attach");
356 if ((so->so_state & SS_PRIV) == 0) {
357 error = EACCES;
358 break;
359 }
360 if ((error = soreserve(so, rip_sendspace, rip_recvspace)) ||
361 (error = in_pcballoc(so, &rawcbtable)))
362 break;
363 inp = (struct inpcb *)so->so_pcb;
364 inp->inp_ip.ip_p = (long)nam;
365 break;
366
367 case PRU_DISCONNECT:
368 if ((so->so_state & SS_ISCONNECTED) == 0) {
369 error = ENOTCONN;
370 break;
371 }
372
373 case PRU_ABORT:
374 soisdisconnected(so);
375
376 case PRU_DETACH:
377 if (inp == 0)
378 panic("rip_detach");
379 #ifdef MROUTING
380 if (so == ip_mrouter)
381 ip_mrouter_done();
382 #endif
383 in_pcbdetach(inp);
384 break;
385
386 case PRU_BIND:
387 {
388 struct sockaddr_in *addr = mtod(nam, struct sockaddr_in *);
389
390 if (nam->m_len != sizeof(*addr)) {
391 error = EINVAL;
392 break;
393 }
394 if ((TAILQ_EMPTY(&ifnet)) ||
395 ((addr->sin_family != AF_INET) &&
396 (addr->sin_family != AF_IMPLINK)) ||
397 (addr->sin_addr.s_addr &&
398 ifa_ifwithaddr(sintosa(addr)) == 0)) {
399 error = EADDRNOTAVAIL;
400 break;
401 }
402 inp->inp_laddr = addr->sin_addr;
403 break;
404 }
405 case PRU_CONNECT:
406 {
407 struct sockaddr_in *addr = mtod(nam, struct sockaddr_in *);
408
409 if (nam->m_len != sizeof(*addr)) {
410 error = EINVAL;
411 break;
412 }
413 if (TAILQ_EMPTY(&ifnet)) {
414 error = EADDRNOTAVAIL;
415 break;
416 }
417 if ((addr->sin_family != AF_INET) &&
418 (addr->sin_family != AF_IMPLINK)) {
419 error = EAFNOSUPPORT;
420 break;
421 }
422 inp->inp_faddr = addr->sin_addr;
423 soisconnected(so);
424 break;
425 }
426
427 case PRU_CONNECT2:
428 error = EOPNOTSUPP;
429 break;
430
431
432
433
434 case PRU_SHUTDOWN:
435 socantsendmore(so);
436 break;
437
438
439
440
441
442 case PRU_SEND:
443 {
444 u_int32_t dst;
445
446 if (so->so_state & SS_ISCONNECTED) {
447 if (nam) {
448 error = EISCONN;
449 break;
450 }
451 dst = inp->inp_faddr.s_addr;
452 } else {
453 if (nam == NULL) {
454 error = ENOTCONN;
455 break;
456 }
457 dst = mtod(nam, struct sockaddr_in *)->sin_addr.s_addr;
458 }
459 #ifdef IPSEC
460
461 #endif
462 error = rip_output(m, so, dst);
463 m = NULL;
464 break;
465 }
466
467 case PRU_SENSE:
468
469
470
471 return (0);
472
473
474
475
476 case PRU_RCVOOB:
477 case PRU_RCVD:
478 case PRU_LISTEN:
479 case PRU_ACCEPT:
480 case PRU_SENDOOB:
481 error = EOPNOTSUPP;
482 break;
483
484 case PRU_SOCKADDR:
485 in_setsockaddr(inp, nam);
486 break;
487
488 case PRU_PEERADDR:
489 in_setpeeraddr(inp, nam);
490 break;
491
492 default:
493 panic("rip_usrreq");
494 }
495 release:
496 if (m != NULL)
497 m_freem(m);
498 return (error);
499 }