1 | /* A sample version of rip_output() from /sys/netinet/raw_ip.c */ |
---|
2 | |
---|
3 | rip_output(m, so) |
---|
4 | register struct mbuf *m; |
---|
5 | struct socket *so; |
---|
6 | { |
---|
7 | register struct ip *ip; |
---|
8 | int error; |
---|
9 | struct rawcb *rp = sotorawcb(so); |
---|
10 | struct sockaddr_in *sin; |
---|
11 | #if BSD>=43 |
---|
12 | short proto = rp->rcb_proto.sp_protocol; |
---|
13 | #else |
---|
14 | short proto = so->so_proto->pr_protocol; |
---|
15 | #endif |
---|
16 | /* |
---|
17 | * if the protocol is IPPROTO_RAW, the user handed us a |
---|
18 | * complete IP packet. Otherwise, allocate an mbuf for a |
---|
19 | * header and fill it in as needed. |
---|
20 | */ |
---|
21 | if (proto != IPPROTO_RAW) { |
---|
22 | /* |
---|
23 | * Calculate data length and get an mbuf |
---|
24 | * for IP header. |
---|
25 | */ |
---|
26 | int len = 0; |
---|
27 | struct mbuf *m0; |
---|
28 | |
---|
29 | for (m0 = m; m; m = m->m_next) |
---|
30 | len += m->m_len; |
---|
31 | |
---|
32 | m = m_get(M_DONTWAIT, MT_HEADER); |
---|
33 | if (m == 0) { |
---|
34 | m = m0; |
---|
35 | error = ENOBUFS; |
---|
36 | goto bad; |
---|
37 | } |
---|
38 | m->m_off = MMAXOFF - sizeof(struct ip); |
---|
39 | m->m_len = sizeof(struct ip); |
---|
40 | m->m_next = m0; |
---|
41 | |
---|
42 | ip = mtod(m, struct ip *); |
---|
43 | ip->ip_tos = 0; |
---|
44 | ip->ip_off = 0; |
---|
45 | ip->ip_p = proto; |
---|
46 | ip->ip_len = sizeof(struct ip) + len; |
---|
47 | ip->ip_ttl = MAXTTL; |
---|
48 | } else |
---|
49 | ip = mtod(m, struct ip *); |
---|
50 | |
---|
51 | if (rp->rcb_flags & RAW_LADDR) { |
---|
52 | sin = (struct sockaddr_in *)&rp->rcb_laddr; |
---|
53 | if (sin->sin_family != AF_INET) { |
---|
54 | error = EAFNOSUPPORT; |
---|
55 | goto bad; |
---|
56 | } |
---|
57 | ip->ip_src.s_addr = sin->sin_addr.s_addr; |
---|
58 | } else |
---|
59 | ip->ip_src.s_addr = 0; |
---|
60 | |
---|
61 | ip->ip_dst = ((struct sockaddr_in *)&rp->rcb_faddr)->sin_addr; |
---|
62 | |
---|
63 | #if BSD>=43 |
---|
64 | return (ip_output(m, rp->rcb_options, &rp->rcb_route, |
---|
65 | (so->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST)); |
---|
66 | #else |
---|
67 | return (ip_output(m, (struct mbuf *)0, &rp->rcb_route, |
---|
68 | (so->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST)); |
---|
69 | #endif |
---|
70 | bad: |
---|
71 | m_freem(m); |
---|
72 | return (error); |
---|
73 | } |
---|