1 /*
2  * Copyright (c) 1990 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  *
7  *	@(#)ccitt_addr.c	5.2 (Berkeley) 04/29/91
8  */
9 /*
10  * parse CCITT addresses
11  *
12  * Addresses must have the format: [hpr],x121address[,userdata][,protocol]
13  * items enclosed with square brackets are optional
14  * 'h' or 'p' means hi priority (packet size = 128; specific to Datapac
15  * and necessary only for X.25(76) and non-negotiating X.25(80) DTE's)
16  * 'r' means reverse charge (remote DTE pays for call).
17  * The x121address consists of an optional netid and dot, followed
18  * by a dte address.
19  *
20  * Frank Pronk
21  * The University of British Columbia
22  * Laboratory for Computational Vision
23  * Copyright (c) 1984
24  */
25 
26 #include <sys/types.h>
27 #include <sys/socket.h>
28 #include <netccitt/x25.h>
29 
30 static char *copychar ();
31 
32 ccitt_addr (addr, xp)
33 char *addr;
34 register struct sockaddr_x25 *xp;
35 {
36 	register char *p, *ap, *limit;
37 	register int havenet = 0;
38 
39 	bzero ((char *)xp, sizeof (*xp));
40 	xp->x25_family = AF_CCITT;
41 	xp->x25_len = sizeof(*xp);
42 	xp->x25_udlen = 4;
43 	p = addr;
44 
45 	/*
46 	 * process optional priority and reverse charging flags
47 	 */
48 
49 	if (*p == 'p' || *p == 'r' || *p == 'h') {
50 		while (*p == 'p' || *p == 'r' || *p == 'h') {
51 			if (*p == 'p' || *p == 'h')
52 				xp->x25_opts.op_psize = X25_PS128;
53 			else if (*p == 'r')
54 				xp->x25_opts.op_flags |= X25_REVERSE_CHARGE;
55 			p++;
56 		}
57 		if (*p != ',')
58 			return (0);
59 		p++;
60 	}
61 	if (*p == '\0')
62 		return (0);
63 
64 	/*
65 	 * [network id:]X.121 address
66 	 */
67 
68 	ap = xp->x25_addr;
69 	limit = ap + sizeof (xp->x25_addr) - 1;
70 	while (*p) {
71 		if (*p == ',')
72 			break;
73 		if (*p == '.' || *p == ':') {
74 			if (havenet)
75 				return (0);
76 			havenet++;
77 			xp->x25_net = atoi (xp->x25_addr);
78 			p++;
79 			ap = xp->x25_addr;
80 			*ap = '\0';
81 		}
82 		if (*p < '0' || *p > '9')
83 			return (0);
84 		if (ap >= limit)
85 			return (0);
86 		*ap++ = *p++;
87 	}
88 	if (*p == '\0')
89 		return (1);
90 
91 	/*
92 	 * optional user data, bytes 4 to 16
93 	 */
94 
95 	p++;
96 	ap = xp->x25_udata + 4;		/* first four bytes are protocol id */
97 	limit = ap + sizeof (xp->x25_udata) - 4;
98 	while (*p) {
99 		if (*p == ',')
100 			break;
101 		if (ap >= limit)
102 			return (0);
103 		p = copychar (p, ap++);
104 		xp->x25_udlen++;
105 	}
106 	if (*p == '\0')
107 		return (1);
108 
109 	p++;
110 	ap = xp->x25_udata;		/* protocol id */
111 	limit = ap + 4;
112 	while (*p) {
113 		if (*p == ',')
114 			return (0);
115 		if (ap >= limit)
116 			return (0);
117 		p = copychar (p, ap++);
118 	}
119 	return (1);
120 }
121 
122 static char *
123 copychar (from, to)
124 register char *from, *to;
125 {
126 	register int n;
127 
128 	if (*from != '\\' || from[1] < '0' || from[1] > '7') {
129 		*to = *from++;
130 		return (from);
131 	}
132 	n = *++from - '0';
133 	from++;
134 	if (*from >= '0' && *from <= '7') {
135 		register int n1;
136 
137 		n = n*8 + *from++ - '0';
138 		if (*from >= '0' && *from <= '7' && (n1 = n*8 + *from-'0') < 256) {
139 			n = n1;
140 			from++;
141 		}
142 	}
143 	*to = n;
144 	return (from);
145 }
146