[10404] | 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 | } |
---|