1 /* 2 * Copyright (c) 1982 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 * 6 * @(#)raw_ip.c 6.8 (Berkeley) 02/23/86 7 */ 8 9 #include "param.h" 10 #include "mbuf.h" 11 #include "socket.h" 12 #include "protosw.h" 13 #include "socketvar.h" 14 #include "errno.h" 15 16 #include "../net/if.h" 17 #include "../net/route.h" 18 #include "../net/raw_cb.h" 19 20 #include "in.h" 21 #include "in_systm.h" 22 #include "ip.h" 23 #include "ip_var.h" 24 25 /* 26 * Raw interface to IP protocol. 27 */ 28 29 struct sockaddr_in ripdst = { AF_INET }; 30 struct sockaddr_in ripsrc = { AF_INET }; 31 struct sockproto ripproto = { PF_INET }; 32 /* 33 * Setup generic address and protocol structures 34 * for raw_input routine, then pass them along with 35 * mbuf chain. 36 */ 37 rip_input(m) 38 struct mbuf *m; 39 { 40 register struct ip *ip = mtod(m, struct ip *); 41 42 ripproto.sp_protocol = ip->ip_p; 43 ripdst.sin_addr = ip->ip_dst; 44 ripsrc.sin_addr = ip->ip_src; 45 raw_input(m, &ripproto, (struct sockaddr *)&ripsrc, 46 (struct sockaddr *)&ripdst); 47 } 48 49 /* 50 * Generate IP header and pass packet to ip_output. 51 * Tack on options user may have setup with control call. 52 */ 53 rip_output(m0, so) 54 struct mbuf *m0; 55 struct socket *so; 56 { 57 register struct mbuf *m; 58 register struct ip *ip; 59 int len = 0, error; 60 struct rawcb *rp = sotorawcb(so); 61 struct sockaddr_in *sin; 62 63 /* 64 * Calculate data length and get an mbuf 65 * for IP header. 66 */ 67 for (m = m0; m; m = m->m_next) 68 len += m->m_len; 69 m = m_get(M_DONTWAIT, MT_HEADER); 70 if (m == 0) { 71 error = ENOBUFS; 72 goto bad; 73 } 74 75 /* 76 * Fill in IP header as needed. 77 */ 78 m->m_off = MMAXOFF - sizeof(struct ip); 79 m->m_len = sizeof(struct ip); 80 m->m_next = m0; 81 ip = mtod(m, struct ip *); 82 ip->ip_tos = 0; 83 ip->ip_off = 0; 84 ip->ip_p = rp->rcb_proto.sp_protocol; 85 ip->ip_len = sizeof(struct ip) + len; 86 if (rp->rcb_flags & RAW_LADDR) { 87 sin = (struct sockaddr_in *)&rp->rcb_laddr; 88 if (sin->sin_family != AF_INET) { 89 error = EAFNOSUPPORT; 90 goto bad; 91 } 92 ip->ip_src.s_addr = sin->sin_addr.s_addr; 93 } else 94 ip->ip_src.s_addr = 0; 95 ip->ip_dst = ((struct sockaddr_in *)&rp->rcb_faddr)->sin_addr; 96 ip->ip_ttl = MAXTTL; 97 return (ip_output(m, rp->rcb_options, &rp->rcb_route, 98 (so->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST)); 99 bad: 100 m_freem(m); 101 return (error); 102 } 103 104 /* 105 * Raw IP socket option processing. 106 */ 107 rip_ctloutput(op, so, level, optname, m) 108 int op; 109 struct socket *so; 110 int level, optname; 111 struct mbuf **m; 112 { 113 int error = 0; 114 register struct rawcb *rp = sotorawcb(so); 115 116 if (level != IPPROTO_IP) 117 error = EINVAL; 118 else switch (op) { 119 120 case PRCO_SETOPT: 121 switch (optname) { 122 case IP_OPTIONS: 123 return (ip_pcbopts(&rp->rcb_options, *m)); 124 125 default: 126 error = EINVAL; 127 break; 128 } 129 break; 130 131 case PRCO_GETOPT: 132 switch (optname) { 133 case IP_OPTIONS: 134 *m = m_get(M_WAIT, MT_SOOPTS); 135 if (rp->rcb_options) { 136 (*m)->m_off = rp->rcb_options->m_off; 137 (*m)->m_len = rp->rcb_options->m_len; 138 bcopy(mtod(rp->rcb_options, caddr_t), 139 mtod(*m, caddr_t), (unsigned)(*m)->m_len); 140 } else 141 (*m)->m_len = 0; 142 break; 143 default: 144 error = EINVAL; 145 break; 146 } 147 break; 148 } 149 if (op == PRCO_SETOPT) 150 (void)m_free(*m); 151 return (error); 152 } 153