minix/servers/inet/generic/ip_lib.c

238 lines
4.5 KiB
C
Raw Normal View History

2005-04-21 16:53:53 +02:00
/*
ip_lib.c
Copyright 1995 Philip Homburg
*/
#include "inet.h"
#include "buf.h"
#include "event.h"
#include "type.h"
#include "assert.h"
#include "io.h"
#include "ip_int.h"
THIS_FILE
PUBLIC ipaddr_t ip_get_netmask (hostaddr)
ipaddr_t hostaddr;
{
return ip_netmask(ip_nettype(hostaddr));
}
PUBLIC int ip_chk_hdropt (opt, optlen)
u8_t *opt;
int optlen;
{
int i, security_present= FALSE, lose_source_present= FALSE,
strict_source_present= FALSE, record_route_present= FALSE,
timestamp_present= FALSE;
assert (!(optlen & 3));
2005-04-21 16:53:53 +02:00
i= 0;
while (i<optlen)
{
DBLOCK(2, printf("*opt= %d\n", *opt));
2005-04-21 16:53:53 +02:00
switch (*opt)
{
case IP_OPT_EOL: /* End of Option list */
2005-04-21 16:53:53 +02:00
return NW_OK;
case IP_OPT_NOP: /* No Operation */
2005-04-21 16:53:53 +02:00
i++;
opt++;
break;
case IP_OPT_SEC: /* Security */
2005-04-21 16:53:53 +02:00
if (security_present)
return EINVAL;
security_present= TRUE;
if (opt[1] != 11)
return EINVAL;
i += opt[1];
opt += opt[1];
break;
case IP_OPT_LSRR: /* Lose Source and Record Route */
2005-04-21 16:53:53 +02:00
if (lose_source_present)
{
DBLOCK(1, printf("2nd lose soruce route\n"));
2005-04-21 16:53:53 +02:00
return EINVAL;
}
lose_source_present= TRUE;
if (opt[1]<3)
{
DBLOCK(1,
printf("wrong length in source route\n"));
return EINVAL;
}
i += opt[1];
opt += opt[1];
break;
case IP_OPT_SSRR: /* Strict Source and Record Route */
2005-04-21 16:53:53 +02:00
if (strict_source_present)
return EINVAL;
strict_source_present= TRUE;
if (opt[1]<3)
return EINVAL;
i += opt[1];
opt += opt[1];
break;
case IP_OPT_RR: /* Record Route */
2005-04-21 16:53:53 +02:00
if (record_route_present)
return EINVAL;
record_route_present= TRUE;
if (opt[1]<3)
return EINVAL;
i += opt[1];
opt += opt[1];
break;
case IP_OPT_TS: /* Timestamp */
2005-04-21 16:53:53 +02:00
if (timestamp_present)
return EINVAL;
timestamp_present= TRUE;
if (opt[1] != 4)
return EINVAL;
switch (opt[3] & 0xff)
{
case 0:
case 1:
case 3:
break;
default:
return EINVAL;
}
i += opt[1];
opt += opt[1];
break;
case IP_OPT_RTRALT:
if (opt[1] != 4)
return EINVAL;
i += opt[1];
opt += opt[1];
break;
2005-04-21 16:53:53 +02:00
default:
return EINVAL;
}
}
if (i > optlen)
{
DBLOCK(1, printf("option of wrong length\n"));
return EINVAL;
}
return NW_OK;
}
PUBLIC void ip_print_frags(acc)
acc_t *acc;
{
#if DEBUG
ip_hdr_t *ip_hdr;
int first;
if (!acc)
printf("(null)");
for (first= 1; acc; acc= acc->acc_ext_link, first= 0)
{
assert (acc->acc_length >= IP_MIN_HDR_SIZE);
ip_hdr= (ip_hdr_t *)ptr2acc_data(acc);
if (first)
{
writeIpAddr(ip_hdr->ih_src);
printf(" > ");
writeIpAddr(ip_hdr->ih_dst);
}
printf(" {%x:%d@%d%c}", ntohs(ip_hdr->ih_id),
ntohs(ip_hdr->ih_length),
(ntohs(ip_hdr->ih_flags_fragoff) & IH_FRAGOFF_MASK)*8,
(ntohs(ip_hdr->ih_flags_fragoff) & IH_MORE_FRAGS) ?
'+' : '\0');
}
#endif
}
PUBLIC ipaddr_t ip_get_ifaddr(port_nr)
int port_nr;
{
assert(port_nr >= 0 && port_nr < ip_conf_nr);
return ip_port_table[port_nr].ip_ipaddr;
}
PUBLIC nettype_t ip_nettype(ipaddr)
ipaddr_t ipaddr;
{
u8_t highbyte;
nettype_t nettype;
ipaddr= ntohl(ipaddr);
highbyte= (ipaddr >> 24) & 0xff;
if (highbyte == 0)
{
if (ipaddr == 0)
nettype= IPNT_ZERO;
else
nettype= IPNT_MARTIAN;
}
else if (highbyte < 127)
nettype= IPNT_CLASS_A;
else if (highbyte == 127)
nettype= IPNT_LOCAL;
else if (highbyte < 192)
nettype= IPNT_CLASS_B;
else if (highbyte < 224)
nettype= IPNT_CLASS_C;
else if (highbyte < 240)
nettype= IPNT_CLASS_D;
else if (highbyte < 248)
nettype= IPNT_CLASS_E;
else if (highbyte < 255)
nettype= IPNT_MARTIAN;
else
{
if (ipaddr == (ipaddr_t)-1)
nettype= IPNT_BROADCAST;
else
nettype= IPNT_MARTIAN;
}
return nettype;
}
PUBLIC ipaddr_t ip_netmask(nettype)
nettype_t nettype;
{
switch(nettype)
{
case IPNT_ZERO: return HTONL(0x00000000);
case IPNT_CLASS_A:
case IPNT_LOCAL: return HTONL(0xff000000);
case IPNT_CLASS_B: return HTONL(0xffff0000);
case IPNT_CLASS_C: return HTONL(0xffffff00);
default: return HTONL(0xffffffff);
}
}
#if 0
PUBLIC char *ip_nettoa(nettype)
nettype_t nettype;
{
switch(nettype)
{
case IPNT_ZERO: return "zero";
case IPNT_CLASS_A: return "class A";
case IPNT_LOCAL: return "local";
case IPNT_CLASS_B: return "class B";
case IPNT_CLASS_C: return "class C";
case IPNT_CLASS_D: return "class D";
case IPNT_CLASS_E: return "class E";
case IPNT_MARTIAN: return "martian";
case IPNT_BROADCAST: return "broadcast";
default: return "<unknown>";
}
}
#endif
/*
* $PchId: ip_lib.c,v 1.10 2002/06/08 21:35:52 philip Exp $
2005-04-21 16:53:53 +02:00
*/