1 /* 2 * Copyright (c) 1982, 1986 Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that the above copyright notice and this paragraph are 7 * duplicated in all such forms and that any documentation, 8 * advertising materials, and other materials related to such 9 * distribution and use acknowledge that the software was developed 10 * by the University of California, Berkeley. The name of the 11 * University may not be used to endorse or promote products derived 12 * from this software without specific prior written permission. 13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16 * 17 * @(#)raw_ip.c 7.4 (Berkeley) 06/29/88 18 */ 19 20 #include "param.h" 21 #include "mbuf.h" 22 #include "socket.h" 23 #include "protosw.h" 24 #include "socketvar.h" 25 #include "errno.h" 26 27 #include "../net/if.h" 28 #include "../net/route.h" 29 #include "../net/raw_cb.h" 30 31 #include "in.h" 32 #include "in_systm.h" 33 #include "ip.h" 34 #include "ip_var.h" 35 36 /* 37 * Raw interface to IP protocol. 38 */ 39 40 struct sockaddr_in ripdst = { AF_INET }; 41 struct sockaddr_in ripsrc = { AF_INET }; 42 struct sockproto ripproto = { PF_INET }; 43 /* 44 * Setup generic address and protocol structures 45 * for raw_input routine, then pass them along with 46 * mbuf chain. 47 */ 48 rip_input(m) 49 struct mbuf *m; 50 { 51 register struct ip *ip = mtod(m, struct ip *); 52 53 ripproto.sp_protocol = ip->ip_p; 54 ripdst.sin_addr = ip->ip_dst; 55 ripsrc.sin_addr = ip->ip_src; 56 raw_input(m, &ripproto, (struct sockaddr *)&ripsrc, 57 (struct sockaddr *)&ripdst); 58 } 59 60 /* 61 * Generate IP header and pass packet to ip_output. 62 * Tack on options user may have setup with control call. 63 */ 64 rip_output(m0, so) 65 struct mbuf *m0; 66 struct socket *so; 67 { 68 register struct mbuf *m; 69 register struct ip *ip; 70 int len = 0, error; 71 struct rawcb *rp = sotorawcb(so); 72 struct sockaddr_in *sin; 73 74 /* 75 * Calculate data length and get an mbuf 76 * for IP header. 77 */ 78 for (m = m0; m; m = m->m_next) 79 len += m->m_len; 80 m = m_get(M_DONTWAIT, MT_HEADER); 81 if (m == 0) { 82 error = ENOBUFS; 83 goto bad; 84 } 85 86 /* 87 * Fill in IP header as needed. 88 */ 89 m->m_off = MMAXOFF - sizeof(struct ip); 90 m->m_len = sizeof(struct ip); 91 m->m_next = m0; 92 ip = mtod(m, struct ip *); 93 ip->ip_tos = 0; 94 ip->ip_off = 0; 95 ip->ip_p = rp->rcb_proto.sp_protocol; 96 ip->ip_len = sizeof(struct ip) + len; 97 if (rp->rcb_flags & RAW_LADDR) { 98 sin = (struct sockaddr_in *)&rp->rcb_laddr; 99 if (sin->sin_family != AF_INET) { 100 error = EAFNOSUPPORT; 101 goto bad; 102 } 103 ip->ip_src.s_addr = sin->sin_addr.s_addr; 104 } else 105 ip->ip_src.s_addr = 0; 106 ip->ip_dst = ((struct sockaddr_in *)&rp->rcb_faddr)->sin_addr; 107 ip->ip_ttl = MAXTTL; 108 return (ip_output(m, rp->rcb_options, &rp->rcb_route, 109 (so->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST)); 110 bad: 111 m_freem(m); 112 return (error); 113 } 114 115 /* 116 * Raw IP socket option processing. 117 */ 118 rip_ctloutput(op, so, level, optname, m) 119 int op; 120 struct socket *so; 121 int level, optname; 122 struct mbuf **m; 123 { 124 int error = 0; 125 register struct rawcb *rp = sotorawcb(so); 126 127 if (level != IPPROTO_IP) 128 error = EINVAL; 129 else switch (op) { 130 131 case PRCO_SETOPT: 132 switch (optname) { 133 case IP_OPTIONS: 134 return (ip_pcbopts(&rp->rcb_options, *m)); 135 136 default: 137 error = EINVAL; 138 break; 139 } 140 break; 141 142 case PRCO_GETOPT: 143 switch (optname) { 144 case IP_OPTIONS: 145 *m = m_get(M_WAIT, MT_SOOPTS); 146 if (rp->rcb_options) { 147 (*m)->m_off = rp->rcb_options->m_off; 148 (*m)->m_len = rp->rcb_options->m_len; 149 bcopy(mtod(rp->rcb_options, caddr_t), 150 mtod(*m, caddr_t), (unsigned)(*m)->m_len); 151 } else 152 (*m)->m_len = 0; 153 break; 154 default: 155 error = EINVAL; 156 break; 157 } 158 break; 159 } 160 if (op == PRCO_SETOPT && *m) 161 (void)m_free(*m); 162 return (error); 163 } 164