1 /* text2qos.c - Converts textual representation of QOS parameters to binary
2 		encoding */
3 
4 /* Written 1996-2000 by Werner Almesberger, EPFL-LRC/ICA */
5 
6 #if HAVE_CONFIG_H
7 #include <config.h>
8 #endif
9 
10 #include <stdlib.h>
11 #include <stdarg.h>
12 #include <string.h>
13 #include <ctype.h>
14 #include <limits.h>
15 
16 #include "atm.h"
17 
18 
19 #define fetch __atmlib_fetch
20 
21 
22 #define RATE_ERROR -2
23 
24 
__t2q_get_rate(const char ** text,int up)25 int __t2q_get_rate(const char **text,int up)
26 {
27     const char mult[] = "kKmMgGg";
28     const char *multiplier;
29     char *end;
30     unsigned int rate,fract;
31     int power;
32 
33     if (!strncmp(*text,"max",3)) {
34 	*text += 3;
35 	return ATM_MAX_PCR;
36     }
37     rate = strtoul(*text,&end,10);
38     power = fract = 0;
39     if (*end == '.')
40 	for (end++; *end && isdigit(*end); end++) {
41 	    fract = fract*10+*end-48;
42 	    if (--power == -9) break;
43 	}
44     multiplier = NULL;
45     if (*end && (multiplier = strchr(mult,*end))) {
46 	while (multiplier >= mult) {
47 	    if (rate > UINT_MAX/1000) return RATE_ERROR;
48 	    rate *= 1000;
49 	    power += 3;
50 	    multiplier -= 2;
51 	}
52 	end++;
53     }
54     while (power && fract)
55 	if (power < 0) {
56 	    fract /= 10;
57 	    power++;
58 	}
59 	else {
60 	    fract *= 10;
61 	    power--;
62 	}
63     rate += fract;
64     if (strlen(end) < 3) {
65 	if (multiplier) return RATE_ERROR;
66     }
67     else if (!strncmp(end,"cps",3)) end += 3;
68 	else if (!strncmp(end,"bps",3)) {
69 		rate = (rate+(up ? 8*ATM_CELL_PAYLOAD-1 : 0))/8/
70 		  ATM_CELL_PAYLOAD;
71 		end += 3;
72 	    }
73 	    else if (multiplier) return RATE_ERROR;
74     if (rate > INT_MAX) return RATE_ERROR;
75     *text = end;
76     return rate;
77 }
78 
79 
params(const char ** text,struct atm_trafprm * a,struct atm_trafprm * b)80 static int params(const char **text,struct atm_trafprm *a,
81   struct atm_trafprm *b)
82 {
83     int value;
84     char *end;
85 
86     if (*(*text)++ != ':') return -1;
87     while (1) {
88 	if (!**text) return -1;
89 	switch (fetch(text,"max_pcr=","pcr=","min_pcr=","max_sdu=","sdu=",
90 	  NULL)) {
91 	    case 0:
92 		if ((value = __t2q_get_rate(text,0)) == RATE_ERROR) return -1;
93 		if (a) a->max_pcr = value;
94 		if (b) b->max_pcr = value;
95 		break;
96 	    case 1:
97 		if ((value = __t2q_get_rate(text,0)) == RATE_ERROR) return -1;
98 		if (a) a->pcr = value;
99 		if (b) b->pcr = value;
100 		break;
101 	    case 2:
102 		if ((value = __t2q_get_rate(text,1)) == RATE_ERROR) return -1;
103 		if (value == ATM_MAX_PCR) return -1;
104 		if (a) a->min_pcr = value;
105 		if (b) b->min_pcr = value;
106 		break;
107 	    case 3:
108 	    case 4:
109 		value = strtol(*text,&end,10);
110 		if (value < 0) return -1;
111 		*text = end;
112 		if (a) a->max_sdu = value;
113 		if (b) b->max_sdu = value;
114 		break;
115 	    default:
116 		return 0;
117 	}
118 	if (!**text) break;
119 	if (*(*text)++ != ',') return -1;
120     }
121     return 0;
122 }
123 
124 
text2qos(const char * text,struct atm_qos * qos,int flags)125 int text2qos(const char *text,struct atm_qos *qos,int flags)
126 {
127     int traffic_class,aal;
128 
129     traffic_class = ATM_NONE;
130     aal = ATM_NO_AAL;
131     do {
132 	static const unsigned char aal_number[] = { ATM_AAL0, ATM_AAL5 };
133 	int item;
134 
135 	item = fetch(&text,"!none","ubr","cbr","vbr","abr","aal0","aal5",NULL);
136 	switch (item) {
137 	    case 1:
138 	    case 2:
139 		/* we don't support VBR yet */
140 	    case 4:
141 		traffic_class = item;
142 		break;
143 	    case 5:
144 	    case 6:
145 		aal = aal_number[item-5];
146 		break;
147 	    default:
148 		return -1;
149 	}
150     }
151     while (*text == ',' ? text++ : 0);
152     if (!traffic_class) return -1;
153     if (qos && !(flags & T2Q_DEFAULTS)) memset(qos,0,sizeof(*qos));
154     if (qos) qos->txtp.traffic_class = qos->rxtp.traffic_class = traffic_class;
155     if (qos && aal) qos->aal = aal;
156     if (!*text) return 0;
157     if (params(&text,qos ? &qos->txtp : NULL,qos ? &qos->rxtp : NULL))
158 	return -1;
159     if (!*text) return 0;
160     switch (fetch(&text,"tx","rx",NULL)) {
161 	case 0:
162 	    if (!fetch(&text,":none",NULL)) {
163 		if (qos) qos->txtp.traffic_class = ATM_NONE;
164 		if (*text == ',') text++;
165 		break;
166 	    }
167 	    if (params(&text,qos ? &qos->txtp : NULL,NULL)) return -1;
168 	    break;
169 	case 1:
170 	    text -= 2;
171 	    break;
172 	default:
173 	    return -1;
174     }
175     if (!*text) return 0;
176     if (fetch(&text,"rx",NULL)) return -1;
177     if (!fetch(&text,":none",NULL) && qos) qos->rxtp.traffic_class = ATM_NONE;
178     else if (params(&text,qos ? &qos->rxtp : NULL,NULL)) return -1;
179     return *text ? -1 : 0;
180 }
181