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
25int __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
80static 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
125int 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