ipsopt.c revision 24583
1139778Simp/*
212115Sdyson * (C)opyright 1995 by Darren Reed.
312115Sdyson *
412115Sdyson * This code may be freely distributed as long as it retains this notice
512115Sdyson * and is not changed in any way.  The author accepts no responsibility
612115Sdyson * for the use of this software.  I hate legaleese, don't you ?
7139778Simp */
812115Sdyson#if !defined(lint) && defined(LIBC_SCCS)
912115Sdysonstatic	char	sccsid[] = "@(#)ipsopt.c	1.2 1/11/96 (C)1995 Darren Reed";
1031495Sphk#endif
1131495Sphk#include <stdio.h>
1231495Sphk#include <string.h>
1331495Sphk#include <sys/types.h>
1431495Sphk#include <sys/time.h>
1512115Sdyson#include <sys/socket.h>
1612115Sdyson#include <netinet/in.h>
1712115Sdyson#include <netinet/in_systm.h>
1812115Sdyson#include <netinet/ip.h>
1912115Sdyson#include "ip_compat.h"
2012115Sdyson
2112115Sdyson
2212115Sdyson#ifndef	__P
2312115Sdyson# ifdef	__STDC__
2412115Sdyson#  define	__P(x)	x
2512115Sdyson# else
2612115Sdyson#  define	__P(x)	()
2712115Sdyson# endif
2812115Sdyson#endif
2912115Sdyson
3012115Sdyson
3112115Sdysonstruct ipopt_names {
3212115Sdyson	int	on_value;
3312115Sdyson	int	on_bit;
3412115Sdyson	int	on_siz;
3512115Sdyson	char	*on_name;
3612115Sdyson};
3712115Sdyson
3812115Sdysonstruct ipopt_names ionames[] = {
3912115Sdyson	{ IPOPT_EOL,	0x01,	1, "eol" },
4093015Sbde	{ IPOPT_NOP,	0x02,	1, "nop" },
4131495Sphk	{ IPOPT_RR,	0x04,	7, "rr" },	/* 1 route */
4253101Seivind	{ IPOPT_TS,	0x08,	8, "ts" },	/* 1 TS */
4312115Sdyson	{ IPOPT_SECURITY, 0x08,	11, "sec-level" },
4412115Sdyson	{ IPOPT_LSRR,	0x10,	7, "lsrr" },	/* 1 route */
4531749Seivind	{ IPOPT_SATID,	0x20,	4, "satid" },
4631398Sbde	{ IPOPT_SSRR,	0x40,	7, "ssrr" },	/* 1 route */
4712115Sdyson	{ 0, 0, 0, NULL }	/* must be last */
4812115Sdyson};
4912115Sdyson
5096749Siedowsestruct	ipopt_names secnames[] = {
51252956Spfg	{ IPOPT_SECUR_UNCLASS,	0x0100,	0, "unclass" },
5212115Sdyson	{ IPOPT_SECUR_CONFID,	0x0200,	0, "confid" },
5360041Sphk	{ IPOPT_SECUR_EFTO,	0x0400,	0, "efto" },
5412115Sdyson	{ IPOPT_SECUR_MMMM,	0x0800,	0, "mmmm" },
55193377Sstas	{ IPOPT_SECUR_RESTR,	0x1000,	0, "restr" },
56164033Srwatson	{ IPOPT_SECUR_SECRET,	0x2000,	0, "secret" },
57271467Spfg	{ IPOPT_SECUR_TOPSECRET, 0x4000,0, "topsecret" },
5812115Sdyson	{ 0, 0, 0, NULL }	/* must be last */
5996749Siedowse};
6026641Sbde
6112115Sdyson
6231268Sphku_short seclevel __P((char *));
6396749Siedowseu_long optname __P((char *, char *));
6496749Siedowse
6596749Siedowse
6696749Siedowseu_short seclevel(slevel)
67322711Spfgchar *slevel;
6812115Sdyson{
6912115Sdyson	struct ipopt_names *so;
70271467Spfg
71271467Spfg	for (so = secnames; so->on_name; so++)
72271467Spfg		if (!strcasecmp(slevel, so->on_name))
73228507Spfg			break;
74271467Spfg
7533933Smsmith	if (!so->on_name) {
7612115Sdyson		fprintf(stderr, "no such security level: %s\n", slevel);
77228507Spfg		return 0;
78228507Spfg	}
7931268Sphk	return so->on_value;
8012115Sdyson}
81221128Sjhb
82202283Slulf
83322711Spfgu_long optname(cp, op)
84202283Slulfchar *cp, *op;
85202283Slulf{
86221128Sjhb	struct ipopt_names *io;
87202283Slulf	u_short lvl;
88221128Sjhb	u_long msk = 0;
89322711Spfg	char *s, *t;
9012115Sdyson	int len = 0;
9192728Salfred
92202283Slulf	for (s = strtok(cp, ","); s; s = strtok(NULL, ",")) {
93254260Spfg		if ((t = strchr(s, '=')))
94254260Spfg			*t++ = '\0';
9531268Sphk		for (io = ionames; io->on_name; io++) {
96138270Sphk			if (strcasecmp(s, io->on_name) || (msk & io->on_bit))
9796749Siedowse				continue;
9896749Siedowse			if ((len + io->on_siz) > 48) {
9996749Siedowse				fprintf(stderr, "options too long\n");
100138270Sphk				return 0;
101138270Sphk			}
102138270Sphk			len += io->on_siz;
103138270Sphk			*op++ = io->on_value;
104252956Spfg			if (io->on_siz > 1) {
105138270Sphk				*op++ = io->on_siz;
106138270Sphk				*op++ = IPOPT_MINOFF;
107138270Sphk
108138270Sphk				if (t && !strcasecmp(s, "sec-level")) {
109138270Sphk					lvl = seclevel(t);
110138270Sphk					bcopy(&lvl, op, sizeof(lvl));
111138270Sphk				}
112138270Sphk				op += io->on_siz - 3;
113138270Sphk			}
114138270Sphk			msk |= io->on_bit;
115138270Sphk			break;
116138270Sphk		}
117138270Sphk		if (!io->on_name) {
118138270Sphk			fprintf(stderr, "unknown IP option name %s\n", s);
119138270Sphk			return 0;
120322711Spfg		}
121322711Spfg	}
122322711Spfg	*op++ = IPOPT_EOL;
123322711Spfg	len++;
124166774Spjd	return len;
125138270Sphk}
126138270Sphk