123170Smckusick /* 234853Sbostic * Copyright (c) 1982, 1986, 1988 Regents of the University of California. 333453Skarels * All rights reserved. 423170Smckusick * 533453Skarels * Redistribution and use in source and binary forms are permitted 634853Sbostic * provided that the above copyright notice and this paragraph are 734853Sbostic * duplicated in all such forms and that any documentation, 834853Sbostic * advertising materials, and other materials related to such 934853Sbostic * distribution and use acknowledge that the software was developed 1034853Sbostic * by the University of California, Berkeley. The name of the 1134853Sbostic * University may not be used to endorse or promote products derived 1234853Sbostic * from this software without specific prior written permission. 1334853Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1434853Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1534853Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1633453Skarels * 17*37477Ssklower * @(#)raw_imp.c 7.5 (Berkeley) 04/22/89 1823170Smckusick */ 195637Sroot 2017069Sbloom #include "param.h" 2117069Sbloom #include "mbuf.h" 2217069Sbloom #include "socket.h" 2317069Sbloom #include "protosw.h" 2417069Sbloom #include "socketvar.h" 2517069Sbloom #include "errno.h" 2610900Ssam 2710900Ssam #include "../net/if.h" 2813453Ssam #include "../net/route.h" 2910900Ssam #include "../net/raw_cb.h" 3010900Ssam 318401Swnj #include "../netinet/in.h" 328401Swnj #include "../netinet/in_systm.h" 3318414Skarels #include "../netinet/in_var.h" 34*37477Ssklower #include "../netinet/in_pcb.h" 3517069Sbloom #include "if_imp.h" 365637Sroot 375637Sroot /* 385637Sroot * Raw interface to IMP. 395637Sroot */ 405637Sroot 415637Sroot /* 425637Sroot * Generate IMP leader and pass packet to impoutput. 435637Sroot * The user must create a skeletal leader in order to 445637Sroot * communicate message type, message subtype, etc. 455637Sroot * We fill in holes where needed and verify parameters 465637Sroot * supplied by user. 475637Sroot */ 485847Sroot rimp_output(m, so) 495637Sroot register struct mbuf *m; 505637Sroot struct socket *so; 515637Sroot { 525637Sroot struct mbuf *n; 536509Ssam int len, error = 0; 545647Ssam register struct imp_leader *ip; 555637Sroot register struct sockaddr_in *sin; 56*37477Ssklower register struct raw_inpcb *rp = sotorawinpcb(so); 5718414Skarels struct in_ifaddr *ia; 585772Swnj struct control_leader *cp; 595637Sroot 605637Sroot /* 615637Sroot * Verify user has supplied necessary space 625637Sroot * for the leader and check parameters in it. 635637Sroot */ 64*37477Ssklower if ((m->m_len < sizeof(struct control_leader)) && 656509Ssam (m = m_pullup(m, sizeof(struct control_leader))) == 0) { 666509Ssam error = EMSGSIZE; /* XXX */ 676509Ssam goto bad; 686509Ssam } 695772Swnj cp = mtod(m, struct control_leader *); 705772Swnj if (cp->dl_mtype == IMPTYPE_DATA) 715772Swnj if (m->m_len < sizeof(struct imp_leader) && 726509Ssam (m = m_pullup(m, sizeof(struct imp_leader))) == 0) { 736509Ssam error = EMSGSIZE; /* XXX */ 746509Ssam goto bad; 756509Ssam } 765647Ssam ip = mtod(m, struct imp_leader *); 776509Ssam if (ip->il_format != IMP_NFF) { 786509Ssam error = EMSGSIZE; /* XXX */ 795637Sroot goto bad; 806509Ssam } 815870Sroot #ifdef notdef 825647Ssam if (ip->il_link != IMPLINK_IP && 836509Ssam (ip->il_link<IMPLINK_LOWEXPER || ip->il_link>IMPLINK_HIGHEXPER)) { 846509Ssam error = EPERM; 855637Sroot goto bad; 866509Ssam } 875870Sroot #endif 885637Sroot 895637Sroot /* 905637Sroot * Fill in IMP leader -- impoutput refrains from rebuilding 915637Sroot * the leader when it sees the protocol family PF_IMPLINK. 925637Sroot * (message size calculated by walking through mbuf's) 935637Sroot */ 945637Sroot for (len = 0, n = m; n; n = n->m_next) 955637Sroot len += n->m_len; 966161Ssam ip->il_length = htons((u_short)(len << 3)); 97*37477Ssklower sin = (struct sockaddr_in *)rp->rinp_rcb.rcb_faddr; 9834509Skarels imp_addr_to_leader((struct control_leader *)ip, sin->sin_addr.s_addr); 996339Ssam /* no routing here */ 10018414Skarels ia = in_iaonnetof(in_netof(sin->sin_addr)); 10118414Skarels if (ia) 10218414Skarels return (impoutput(ia->ia_ifp, m, (struct sockaddr *)sin)); 1036509Ssam error = ENETUNREACH; 1045637Sroot bad: 1055637Sroot m_freem(m); 1066509Ssam return (error); 1075637Sroot } 108