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