int va_printf(void (*putc)(int), const char *formato, va_list va) { char buf[16]; char *s, *ps; int c, frac, n, sinal, base, nprinted; int campo,padchar; double x, y; s=(char *)formato; nprinted=campo=0; while((c=*s++)) { if(c=='%'){ c=*s++; sinal=frac=campo=0; padchar = ((c=='0')? '0' + 0x100:' ' + 0x100); if(c=='-') { padchar =' '; c=*s++; } while(edigito(c)) { campo=10*campo+c-'0'; c=*s++; } if(c=='.') { c=*s++; while(edigito(c)) { frac=10*frac+c-'0'; c=*s++; } } while(c=='l' || c=='L' || c=='h') c=*s++; base=10; if(c >= 'A' && c <= 'Z') c ^= 0x20; switch(c){ case 'o': case 'q': base=8; goto lbl_u; case 'x': base=16; case 'u': lbl_u: n = u2str(buf, va_arg(va, unsigned int), base); lbl_escrevei: nprinted += n; campo -= (n+sinal); if(campo < 0) campo=0; nprinted +=campo; if(padchar & 0x100) while(campo--) putc(padchar); if(sinal) putc('-'); while(n--) putc(buf[n]); break; case 'd': case 'i': base=va_arg(va, int); if(base < 0) { sinal=1; base=-base; } n = u2str(buf, base, 10); goto lbl_escrevei; case 'c': if(campo < 0) campo=0; nprinted +=campo; if(padchar & 0x100) while(campo--) putc(padchar); putc(va_arg(va, int)); nprinted++; break; case 's': ps = va_arg(va, char *); for(n=0; ps[n]; n++); nprinted += n; campo -= n; if(campo < 0) campo=0; nprinted +=campo; if(padchar & 0x100) while(campo--) putc(padchar); while(*ps) { putc(*ps); ps++; } break; case 'e': case 'f': case 'g': n=0; x=y=va_arg(va, double); if(x<0) { x=-x; sinal=1; } while((x > 1.0)) { x /= 10.0; n++; } if(x) while((x < 1.0)) { x *= 10.0; n--; } if(c=='e' || ((c=='g') && ((n > 9) || ((-n >= frac)&& frac)))){ y = (sinal ? -x: x); sinal = 2; campo -=4; if(frac<2) frac=2; } c = dprint(y, (padchar & 0x100)?campo:0, frac, putc); campo -=c; nprinted +=c; if(sinal & 2){ putc('E'); if(n < 0) { putc('-'); n=-n; } else putc('+'); if(n>99) { putc((n/100) + '0'); n %= 100; } putc((n / 10) + '0'); putc((n % 10) + '0'); } break; case '%': putc(c); nprinted++; break; } if(campo < 0) campo=0; nprinted +=campo; if(!(padchar & 0x100)) while(campo--) putc(padchar); } else { putc(c); nprinted++; }
static void display_med(struct writer *w, struct lldpd_chassis *chassis, struct lldpd_port *port) { int i; char *value; tag_start(w, "lldp-med", "LLDP-MED"); tag_datatag(w, "device-type", "Device Type", map_lookup(chassis_med_type_map, chassis->c_med_type)); display_med_capability(w, chassis, LLDPMED_CAP_CAP); display_med_capability(w, chassis, LLDPMED_CAP_POLICY); display_med_capability(w, chassis, LLDPMED_CAP_LOCATION); display_med_capability(w, chassis, LLDPMED_CAP_MDI_PSE); display_med_capability(w, chassis, LLDPMED_CAP_MDI_PD); display_med_capability(w, chassis, LLDPMED_CAP_IV); for (i = 0; i < LLDPMED_APPTYPE_LAST; i++) { if (i+1 == port->p_med_policy[i].type) { tag_start(w, "policy", "LLDP-MED Network Policy for"); tag_attr(w, "apptype", "AppType", u2str(port->p_med_policy[i].type)); tag_attr(w, "defined", "Defined", (port->p_med_policy[i].unknown)?"no":"yes"); tag_datatag(w, "descr", "", map_lookup(port_med_policy_map, port->p_med_policy[i].type)); if (port->p_med_policy[i].tagged) { tag_start(w, "vlan", "VLAN"); if (port->p_med_policy[i].vid == 0) { tag_attr(w, "vid", "", "priority"); } else if (port->p_med_policy[i].vid == 4095) { tag_attr(w, "vid", "", "reserved"); } else { tag_attr(w, "vid", "", u2str(port->p_med_policy[i].vid)); } tag_end(w); } tag_datatag(w, "priority", "Layer 2 Priority", u2str(port->p_med_policy[i].priority)); tag_datatag(w, "dscp", "DSCP Value", u2str(port->p_med_policy[i].dscp)); tag_end(w); } } for (i = 0; i < LLDPMED_LOCFORMAT_LAST; i++) { if (i+1 == port->p_med_location[i].format) { tag_start(w, "location", "LLDP-MED Location Identification"); switch(port->p_med_location[i].format) { case LLDPMED_LOCFORMAT_COORD: tag_attr(w, "type", "Type", "coordinates"); if (port->p_med_location[i].data_len != 16) { tag_datatag(w, "error", "Error", "bad data length"); } else { u_int64_t l; u_int8_t v; char * s; v = *(u_int8_t*)(port->p_med_location[i].data + 15); tag_attr(w, "geoid", "Geoid", map_lookup(port_med_geoid_map,v)); /* Latitude and longitude */ memcpy(&l, port->p_med_location[i].data, sizeof(u_int64_t)); l = (ntohll(l) & 0x03FFFFFFFF000000ULL) >> 24; display_latitude_or_longitude(w,0, l); memcpy(&l, port->p_med_location[i].data + 5, sizeof(u_int64_t)); l = (ntohll(l) & 0x03FFFFFFFF000000ULL) >> 24; display_latitude_or_longitude(w,1, l); /* Altitude */ memcpy(&l, port->p_med_location[i].data + 10, sizeof(u_int64_t)); l = (ntohll(l) & 0x3FFFFFFF000000ULL) >> 24; display_fixed_precision(l, 22, 8, 1, &s); tag_start(w, "altitude", "Altitude"); switch ((*(u_int8_t*)(port->p_med_location[i].data + 10)) & 0xf0) { case (1 << 4): tag_attr(w, "unit", "", "m"); break; case (2 << 4): tag_attr(w, "unit", "", "floor"); break; default: tag_attr(w, "unit", "", "unknown"); } tag_data(w,s); tag_end(w); } break; case LLDPMED_LOCFORMAT_CIVIC: tag_attr(w, "type", "Type", "address"); if ((port->p_med_location[i].data_len < 3) || (port->p_med_location[i].data_len - 1 != *(u_int8_t*)port->p_med_location[i].data)) { tag_datatag(w, "error", "Error", "bad data length"); } else { int l = 4, n, catype, calength; char country[3]; country[0] = ((char *)port->p_med_location[i].data)[2]; country[1] = ((char *)port->p_med_location[i].data)[3]; country[2] = 0; tag_datatag(w, "country", "Country", country); while ((n = (port-> p_med_location[i].data_len - l)) >= 2) { catype = *(u_int8_t*)(port-> p_med_location[i].data + l); calength = *(u_int8_t*)(port-> p_med_location[i].data + l + 1); if (n < 2 + calength) { tag_datatag(w, "error", "Error", "bad data length"); break; } if ((value = strndup((char *)(port-> p_med_location[i].data + l + 2), calength)) == NULL) { fatalx("not enough memory"); break; } tag_datatag(w, map_lookup(civic_address_type_tags,catype), map_lookup(civic_address_type_values,catype), value); free(value); l += 2 + calength; } } break; case LLDPMED_LOCFORMAT_ELIN: if ((value = strndup((char *)(port-> p_med_location[i].data), port->p_med_location[i].data_len)) == NULL) { fatalx( "not enough memory"); break; } tag_attr(w, "type", "Type", "elin"); tag_datatag(w, "ecs", "ECS ELIN", value); free(value); break; default: tag_attr(w, "type", "", "unknown"); tag_datatag(w, "unknown", "Data", dump(port->p_med_location[i].data, port->p_med_location[i].data_len, 20, ' ')); } tag_end(w); } }