| /* text2qos.c - Converts textual representation of QOS parameters to binary |
| encoding */ |
| |
| /* Written 1996-2000 by Werner Almesberger, EPFL-LRC/ICA */ |
| |
| #if HAVE_CONFIG_H |
| #include <config.h> |
| #endif |
| |
| #include <stdlib.h> |
| #include <stdarg.h> |
| #include <string.h> |
| #include <ctype.h> |
| #include <limits.h> |
| |
| #include "atm.h" |
| |
| |
| #define fetch __atmlib_fetch |
| |
| |
| #define RATE_ERROR -2 |
| |
| |
| int __t2q_get_rate(const char **text,int up) |
| { |
| const char mult[] = "kKmMgGg"; |
| const char *multiplier; |
| char *end; |
| unsigned int rate,fract; |
| int power; |
| |
| if (!strncmp(*text,"max",3)) { |
| *text += 3; |
| return ATM_MAX_PCR; |
| } |
| rate = strtoul(*text,&end,10); |
| power = fract = 0; |
| if (*end == '.') |
| for (end++; *end && isdigit(*end); end++) { |
| fract = fract*10+*end-48; |
| if (--power == -9) break; |
| } |
| multiplier = NULL; |
| if (*end && (multiplier = strchr(mult,*end))) { |
| while (multiplier >= mult) { |
| if (rate > UINT_MAX/1000) return RATE_ERROR; |
| rate *= 1000; |
| power += 3; |
| multiplier -= 2; |
| } |
| end++; |
| } |
| while (power && fract) |
| if (power < 0) { |
| fract /= 10; |
| power++; |
| } |
| else { |
| fract *= 10; |
| power--; |
| } |
| rate += fract; |
| if (strlen(end) < 3) { |
| if (multiplier) return RATE_ERROR; |
| } |
| else if (!strncmp(end,"cps",3)) end += 3; |
| else if (!strncmp(end,"bps",3)) { |
| rate = (rate+(up ? 8*ATM_CELL_PAYLOAD-1 : 0))/8/ |
| ATM_CELL_PAYLOAD; |
| end += 3; |
| } |
| else if (multiplier) return RATE_ERROR; |
| if (rate > INT_MAX) return RATE_ERROR; |
| *text = end; |
| return rate; |
| } |
| |
| |
| static int params(const char **text,struct atm_trafprm *a, |
| struct atm_trafprm *b) |
| { |
| int value; |
| char *end; |
| |
| if (*(*text)++ != ':') return -1; |
| while (1) { |
| if (!**text) return -1; |
| switch (fetch(text,"max_pcr=","pcr=","min_pcr=","max_sdu=","sdu=", |
| NULL)) { |
| case 0: |
| if ((value = __t2q_get_rate(text,0)) == RATE_ERROR) return -1; |
| if (a) a->max_pcr = value; |
| if (b) b->max_pcr = value; |
| break; |
| case 1: |
| if ((value = __t2q_get_rate(text,0)) == RATE_ERROR) return -1; |
| if (a) a->pcr = value; |
| if (b) b->pcr = value; |
| break; |
| case 2: |
| if ((value = __t2q_get_rate(text,1)) == RATE_ERROR) return -1; |
| if (value == ATM_MAX_PCR) return -1; |
| if (a) a->min_pcr = value; |
| if (b) b->min_pcr = value; |
| break; |
| case 3: |
| case 4: |
| value = strtol(*text,&end,10); |
| if (value < 0) return -1; |
| *text = end; |
| if (a) a->max_sdu = value; |
| if (b) b->max_sdu = value; |
| break; |
| default: |
| return 0; |
| } |
| if (!**text) break; |
| if (*(*text)++ != ',') return -1; |
| } |
| return 0; |
| } |
| |
| |
| int text2qos(const char *text,struct atm_qos *qos,int flags) |
| { |
| int traffic_class,aal; |
| |
| traffic_class = ATM_NONE; |
| aal = ATM_NO_AAL; |
| do { |
| static const unsigned char aal_number[] = { ATM_AAL0, ATM_AAL5 }; |
| int item; |
| |
| item = fetch(&text,"!none","ubr","cbr","vbr","abr","aal0","aal5",NULL); |
| switch (item) { |
| case 1: |
| case 2: |
| /* we don't support VBR yet */ |
| case 4: |
| traffic_class = item; |
| break; |
| case 5: |
| case 6: |
| aal = aal_number[item-5]; |
| break; |
| default: |
| return -1; |
| } |
| } |
| while (*text == ',' ? text++ : 0); |
| if (!traffic_class) return -1; |
| if (qos && !(flags & T2Q_DEFAULTS)) memset(qos,0,sizeof(*qos)); |
| if (qos) qos->txtp.traffic_class = qos->rxtp.traffic_class = traffic_class; |
| if (qos && aal) qos->aal = aal; |
| if (!*text) return 0; |
| if (params(&text,qos ? &qos->txtp : NULL,qos ? &qos->rxtp : NULL)) |
| return -1; |
| if (!*text) return 0; |
| switch (fetch(&text,"tx","rx",NULL)) { |
| case 0: |
| if (!fetch(&text,":none",NULL)) { |
| if (qos) qos->txtp.traffic_class = ATM_NONE; |
| if (*text == ',') text++; |
| break; |
| } |
| if (params(&text,qos ? &qos->txtp : NULL,NULL)) return -1; |
| break; |
| case 1: |
| text -= 2; |
| break; |
| default: |
| return -1; |
| } |
| if (!*text) return 0; |
| if (fetch(&text,"rx",NULL)) return -1; |
| if (!fetch(&text,":none",NULL) && qos) qos->rxtp.traffic_class = ATM_NONE; |
| else if (params(&text,qos ? &qos->rxtp : NULL,NULL)) return -1; |
| return *text ? -1 : 0; |
| } |