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;
|
|
|
|
|
2005-06-28 17:19:58 +02:00
|
|
|
assert (!(optlen & 3));
|
2005-04-21 16:53:53 +02:00
|
|
|
i= 0;
|
|
|
|
while (i<optlen)
|
|
|
|
{
|
2005-06-28 17:19:58 +02:00
|
|
|
DBLOCK(2, printf("*opt= %d\n", *opt));
|
2005-04-21 16:53:53 +02:00
|
|
|
|
|
|
|
switch (*opt)
|
|
|
|
{
|
2005-06-28 17:19:58 +02:00
|
|
|
case IP_OPT_EOL: /* End of Option list */
|
2005-04-21 16:53:53 +02:00
|
|
|
return NW_OK;
|
2005-06-28 17:19:58 +02:00
|
|
|
case IP_OPT_NOP: /* No Operation */
|
2005-04-21 16:53:53 +02:00
|
|
|
i++;
|
|
|
|
opt++;
|
|
|
|
break;
|
2005-06-28 17:19:58 +02:00
|
|
|
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;
|
2005-06-28 17:19:58 +02:00
|
|
|
case IP_OPT_LSRR: /* Lose Source and Record Route */
|
2005-04-21 16:53:53 +02:00
|
|
|
if (lose_source_present)
|
|
|
|
{
|
2005-06-28 17:19:58 +02:00
|
|
|
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;
|
2005-06-28 17:19:58 +02:00
|
|
|
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;
|
2005-06-28 17:19:58 +02:00
|
|
|
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;
|
2005-06-28 17:19:58 +02:00
|
|
|
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;
|
2005-06-28 17:19:58 +02:00
|
|
|
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
|
|
|
|
|
|
|
|
/*
|
2005-06-28 17:19:58 +02:00
|
|
|
* $PchId: ip_lib.c,v 1.10 2002/06/08 21:35:52 philip Exp $
|
2005-04-21 16:53:53 +02:00
|
|
|
*/
|