* Copyright (c) 1982 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
* @(#)ns_ip.c 6.3 (Berkeley) %G%
* Software interface driver for encapsulating ns in ip.
#include "../net/netisr.h"
#include "../net/route.h"
#include "../netinet/in.h"
#include "../netinet/in_systm.h"
#include "../netinet/in_var.h"
#include "../netinet/ip.h"
#include "../netinet/ip_var.h"
#include "../netns/ns_if.h"
#include "../netns/idp.h"
int nsipoutput(), nsipioctl();
#define LOMTU (1024+512);
struct mbuf
*nsip_list
; /* list of all hosts and gateways or
register struct mbuf
*m
= m_getclr(M_DONTWAIT
, MT_PCB
);
register struct ifnet
*ifp
;
register struct sockaddr_in
*sin
;
m
->m_len
= sizeof(struct ifnet_en
);
ifp
= mtod(m
, struct ifnet
*);
ifp
->if_ioctl
= nsipioctl
;
ifp
->if_output
= nsipoutput
;
ifp
->if_flags
= IFF_POINTOPOINT
;
ifp
->if_unit
= nsipif
.if_unit
++;
* Process an ioctl request.
nsipioctl(ifp
, cmd
, data
)
register struct ifnet
*ifp
;
* Everything else is done at a higher level.
struct mbuf
*nsip_badlen
;
struct mbuf
*nsip_lastin
;
register struct idp
*idp
;
register struct ifqueue
*ifq
= &nsintrq
;
nsip_lastin
= m_copy(m0
, 0, M_COPYALL
);
* Get IP and IDP header together in first mbuf.
s
= sizeof (struct ip
) + sizeof (struct idp
);
if ((m
->m_off
> MMAXOFF
|| m
->m_len
< s
) &&
(m
= m_pullup(m
, s
))==0) {
ip
= mtod(m
, struct ip
*);
if (ip
->ip_hl
> (sizeof (struct ip
) >> 2))
ip_stripoptions(ip
, (struct mbuf
*)0);
* Make mbuf data length reflect IDP length.
* If not enough data to reflect IDP length, drop.
m
->m_off
+= sizeof (struct ip
);
m
->m_len
-= sizeof (struct ip
);
idp
= mtod(m
, struct idp
*);
len
= ntohs(idp
->idp_len
);
if (len
& 1) len
++; /* Preserve Garbage Byte */
if(nsip_badlen
) m_freem(nsip_badlen
);
m_adj(m
, len
- ip
->ip_len
);
register struct mbuf
*m
= dtom(ifn
);
register struct route
*ro
= &(ifn
->ifen_route
);
struct in_addr in_src
, in_dst
;
register struct idp
*idp
= mtod(m0
, struct idp
*);
if (m
->m_len
!= sizeof(struct ifnet_en
)) {
printf("nsipoutput: bad dst ifp %x\n", ifn
);
ifn
->ifen_ifnet
.if_opackets
++;
* Calculate data length and make space
len
= ntohs(idp
->idp_len
);
if (len
& 1) len
++; /* Preserve Garbage Byte */
if(m
->m_off
< MMINOFF
+ sizeof (struct ip
)) {
m
= m_get(M_DONTWAIT
, MT_HEADER
);
m
->m_off
= MMAXOFF
- sizeof (struct ip
);
m
->m_len
= sizeof (struct ip
);
m
->m_off
-= sizeof (struct ip
);
m
->m_len
+= sizeof (struct ip
);
ip
= mtod(m
, struct ip
*);
ip
->ip_src
= ifn
->ifen_src
;
ip
->ip_dst
= ifn
->ifen_dst
;
ip
->ip_len
= (u_short
)len
+ sizeof (struct ip
);
error
= (ip_output(m
, (struct mbuf
*)0, ro
, SO_BROADCAST
));
ifn
->ifen_ifnet
.if_oerrors
++;
ifn
->ifen_ifnet
.if_ierrors
= error
;
struct ifreq ifr
= {"nsip0"};
register struct nsip_req
*rq
= mtod(m
, struct nsip_req
*);
struct sockaddr_ns
*ns_dst
= (struct sockaddr_ns
*)&rq
->rq_ns
;
struct sockaddr_in
*ip_dst
= (struct sockaddr_in
*)&rq
->rq_ip
;
int flags
= rq
->rq_flags
;
* First, determine if we can get to the destination
bzero((caddr_t
)&ro
, sizeof (ro
));
ro
.ro_dst
= *(struct sockaddr
*)ip_dst
;
dst
= (struct sockaddr_in
*)& ro
.ro_dst
;
if (ro
.ro_rt
== 0 || (ifp
= ro
.ro_rt
->rt_ifp
) == 0) {
* And see how he's going to get back to us:
register struct in_ifaddr
*ia
;
struct ifnet
*ifp
= ro
.ro_rt
->rt_ifp
;
for (ia
= in_ifaddr
; ia
; ia
= ia
->ia_next
)
src
= (struct sockaddr_in
*)&ia
->ia_addr
;
if (m
==NULL
) {return (ENOBUFS
);}
ifn
= mtod(m
, struct ifnet_en
*);
ifn
->ifen_dst
= ip_dst
->sin_addr
;
ifn
->ifen_src
= src
->sin_addr
;
* now configure this as a point to point link
ifr
.ifr_name
[4] = '0' + nsipif
.if_unit
- 1;
ifr
.ifr_dstaddr
= * (struct sockaddr
*) ns_dst
;
return(ns_control((struct socket
*)0, SIOCSIFADDR
, (caddr_t
)&ifr
,