1*23186Smckusick /* 2*23186Smckusick * Copyright (c) 1982 Regents of the University of California. 3*23186Smckusick * All rights reserved. The Berkeley software License Agreement 4*23186Smckusick * specifies the terms and conditions for redistribution. 5*23186Smckusick * 6*23186Smckusick * @(#)raw_ip.c 6.6 (Berkeley) 06/08/85 7*23186Smckusick */ 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; 9713455Ssam return (ip_output(m, (struct mbuf *)0, &rp->rcb_route, 9812418Ssam IP_ROUTETOIF|IP_ALLOWBROADCAST)); 996509Ssam bad: 1006509Ssam m_freem(m); 1016509Ssam return (error); 1025123Swnj } 103