123186Smckusick /* 229146Smckusick * Copyright (c) 1982, 1986 Regents of the University of California. 323186Smckusick * All rights reserved. The Berkeley software License Agreement 423186Smckusick * specifies the terms and conditions for redistribution. 523186Smckusick * 6*31649Smckusick * @(#)raw_ip.c 7.2 (Berkeley) 06/20/87 723186Smckusick */ 85123Swnj 917062Sbloom #include "param.h" 1017062Sbloom #include "mbuf.h" 1117062Sbloom #include "socket.h" 1217062Sbloom #include "protosw.h" 1317062Sbloom #include "socketvar.h" 1417062Sbloom #include "errno.h" 1510894Ssam 166509Ssam #include "../net/if.h" 1713455Ssam #include "../net/route.h" 1810894Ssam #include "../net/raw_cb.h" 1910894Ssam 2017062Sbloom #include "in.h" 2117062Sbloom #include "in_systm.h" 2217062Sbloom #include "ip.h" 2317062Sbloom #include "ip_var.h" 245123Swnj 255123Swnj /* 265612Swnj * Raw interface to IP protocol. 275123Swnj */ 285612Swnj 2913455Ssam struct sockaddr_in ripdst = { AF_INET }; 3013455Ssam struct sockaddr_in ripsrc = { AF_INET }; 3113455Ssam struct sockproto ripproto = { PF_INET }; 325612Swnj /* 335612Swnj * Setup generic address and protocol structures 345612Swnj * for raw_input routine, then pass them along with 355612Swnj * mbuf chain. 365612Swnj */ 375123Swnj rip_input(m) 385123Swnj struct mbuf *m; 395123Swnj { 405612Swnj register struct ip *ip = mtod(m, struct ip *); 415123Swnj 425612Swnj ripproto.sp_protocol = ip->ip_p; 435646Ssam ripdst.sin_addr = ip->ip_dst; 445646Ssam ripsrc.sin_addr = ip->ip_src; 456529Ssam raw_input(m, &ripproto, (struct sockaddr *)&ripsrc, 466529Ssam (struct sockaddr *)&ripdst); 475123Swnj } 485123Swnj 495612Swnj /* 505612Swnj * Generate IP header and pass packet to ip_output. 515612Swnj * Tack on options user may have setup with control call. 525612Swnj */ 535612Swnj rip_output(m0, so) 545612Swnj struct mbuf *m0; 555612Swnj struct socket *so; 565123Swnj { 575612Swnj register struct mbuf *m; 585612Swnj register struct ip *ip; 596509Ssam int len = 0, error; 606509Ssam struct rawcb *rp = sotorawcb(so); 617156Swnj struct sockaddr_in *sin; 625123Swnj 635612Swnj /* 645612Swnj * Calculate data length and get an mbuf 655612Swnj * for IP header. 665612Swnj */ 675612Swnj for (m = m0; m; m = m->m_next) 685612Swnj len += m->m_len; 699642Ssam m = m_get(M_DONTWAIT, MT_HEADER); 705612Swnj if (m == 0) { 716509Ssam error = ENOBUFS; 726509Ssam goto bad; 735612Swnj } 745612Swnj 755612Swnj /* 765612Swnj * Fill in IP header as needed. 775612Swnj */ 785612Swnj m->m_off = MMAXOFF - sizeof(struct ip); 795612Swnj m->m_len = sizeof(struct ip); 805612Swnj m->m_next = m0; 815612Swnj ip = mtod(m, struct ip *); 8216798Skarels ip->ip_tos = 0; 8315714Skarels ip->ip_off = 0; 8421770Skarels ip->ip_p = rp->rcb_proto.sp_protocol; 855612Swnj ip->ip_len = sizeof(struct ip) + len; 867156Swnj if (rp->rcb_flags & RAW_LADDR) { 877156Swnj sin = (struct sockaddr_in *)&rp->rcb_laddr; 887156Swnj if (sin->sin_family != AF_INET) { 896509Ssam error = EAFNOSUPPORT; 906509Ssam goto bad; 916509Ssam } 927156Swnj ip->ip_src.s_addr = sin->sin_addr.s_addr; 937156Swnj } else 947156Swnj ip->ip_src.s_addr = 0; 957156Swnj ip->ip_dst = ((struct sockaddr_in *)&rp->rcb_faddr)->sin_addr; 965612Swnj ip->ip_ttl = MAXTTL; 9726037Skarels return (ip_output(m, rp->rcb_options, &rp->rcb_route, 9826037Skarels (so->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST)); 996509Ssam bad: 1006509Ssam m_freem(m); 1016509Ssam return (error); 1025123Swnj } 10326037Skarels 10426037Skarels /* 10526037Skarels * Raw IP socket option processing. 10626037Skarels */ 10726037Skarels rip_ctloutput(op, so, level, optname, m) 10826037Skarels int op; 10926037Skarels struct socket *so; 11026037Skarels int level, optname; 11126037Skarels struct mbuf **m; 11226037Skarels { 11326037Skarels int error = 0; 11426037Skarels register struct rawcb *rp = sotorawcb(so); 11526037Skarels 11626037Skarels if (level != IPPROTO_IP) 11726037Skarels error = EINVAL; 11826037Skarels else switch (op) { 11926037Skarels 12026037Skarels case PRCO_SETOPT: 12126037Skarels switch (optname) { 12226037Skarels case IP_OPTIONS: 12326037Skarels return (ip_pcbopts(&rp->rcb_options, *m)); 12426037Skarels 12526037Skarels default: 12626037Skarels error = EINVAL; 12726037Skarels break; 12826037Skarels } 12926037Skarels break; 13026037Skarels 13126037Skarels case PRCO_GETOPT: 13226037Skarels switch (optname) { 13326037Skarels case IP_OPTIONS: 13426037Skarels *m = m_get(M_WAIT, MT_SOOPTS); 13526037Skarels if (rp->rcb_options) { 13626037Skarels (*m)->m_off = rp->rcb_options->m_off; 13726037Skarels (*m)->m_len = rp->rcb_options->m_len; 13826037Skarels bcopy(mtod(rp->rcb_options, caddr_t), 13926386Skarels mtod(*m, caddr_t), (unsigned)(*m)->m_len); 14026037Skarels } else 14126037Skarels (*m)->m_len = 0; 14226037Skarels break; 14326037Skarels default: 14426037Skarels error = EINVAL; 14526037Skarels break; 14626037Skarels } 14726037Skarels break; 14826037Skarels } 149*31649Smckusick if (op == PRCO_SETOPT && *m) 15026386Skarels (void)m_free(*m); 15126037Skarels return (error); 15226037Skarels } 153