mirror_iproute2/tc/q_atm.c
Phil Sutter d17b136f7d Use C99 style initializers everywhere
This big patch was compiled by vimgrepping for memset calls and changing
to C99 initializer if applicable. One notable exception is the
initialization of union bpf_attr in tc/tc_bpf.c: changing it would break
for older gcc versions (at least <=3.4.6).

Calls to memset for struct rtattr pointer fields for parse_rtattr*()
were just dropped since they are not needed.

The changes here allowed the compiler to discover some unused variables,
so get rid of them, too.

Signed-off-by: Phil Sutter <phil@nwl.cc>
Acked-by: David Ahern <dsa@cumulusnetworks.com>
2016-07-20 12:05:24 -07:00

248 lines
5.5 KiB
C

/*
* q_atm.c ATM.
*
* Hacked 1998-2000 by Werner Almesberger, EPFL ICA
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <ctype.h>
#include <syslog.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <atm.h>
#include <linux/atmdev.h>
#include <linux/atmarp.h>
#include "utils.h"
#include "tc_util.h"
#define MAX_HDR_LEN 64
static int atm_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n)
{
if (argc) {
fprintf(stderr, "Usage: atm\n");
return -1;
}
return 0;
}
static void explain(void)
{
fprintf(stderr, "Usage: ... atm ( pvc ADDR | svc ADDR [ sap SAP ] ) [ qos QOS ] [ sndbuf BYTES ]\n");
fprintf(stderr, " [ hdr HEX... ] [ excess ( CLASSID | clp ) ] [ clip ]\n");
}
static int atm_parse_class_opt(struct qdisc_util *qu, int argc, char **argv,
struct nlmsghdr *n)
{
struct sockaddr_atmsvc addr = {};
struct atm_qos qos;
struct atm_sap sap;
unsigned char hdr[MAX_HDR_LEN];
__u32 excess = 0;
struct rtattr *tail;
int sndbuf = 0;
int hdr_len = -1;
int set_clip = 0;
int s;
(void) text2qos("aal5,ubr:sdu=9180,rx:none", &qos, 0);
(void) text2sap("blli:l2=iso8802", &sap, 0);
while (argc > 0) {
if (!strcmp(*argv, "pvc")) {
NEXT_ARG();
if (text2atm(*argv, (struct sockaddr *) &addr,
sizeof(addr), T2A_PVC | T2A_NAME) < 0) {
explain();
return -1;
}
} else if (!strcmp(*argv,"svc")) {
NEXT_ARG();
if (text2atm(*argv, (struct sockaddr *) &addr,
sizeof(addr), T2A_SVC | T2A_NAME) < 0) {
explain();
return -1;
}
} else if (!strcmp(*argv,"qos")) {
NEXT_ARG();
if (text2qos(*argv, &qos, 0) < 0) {
explain();
return -1;
}
} else if (!strcmp(*argv,"sndbuf")) {
char *end;
NEXT_ARG();
sndbuf = strtol(*argv, &end, 0);
if (*end) {
explain();
return -1;
}
} else if (!strcmp(*argv,"sap")) {
NEXT_ARG();
if (addr.sas_family != AF_ATMSVC ||
text2sap(*argv, &sap, T2A_NAME) < 0) {
explain();
return -1;
}
} else if (!strcmp(*argv,"hdr")) {
unsigned char *ptr;
char *walk;
NEXT_ARG();
ptr = hdr;
for (walk = *argv; *walk; walk++) {
int tmp;
if (ptr == hdr+MAX_HDR_LEN) {
fprintf(stderr, "header is too long\n");
return -1;
}
if (*walk == '.') continue;
if (!isxdigit(walk[0]) || !walk[1] ||
!isxdigit(walk[1])) {
explain();
return -1;
}
sscanf(walk, "%2x", &tmp);
*ptr++ = tmp;
walk++;
}
hdr_len = ptr-hdr;
} else if (!strcmp(*argv,"excess")) {
NEXT_ARG();
if (!strcmp(*argv, "clp")) excess = 0;
else if (get_tc_classid(&excess, *argv)) {
explain();
return -1;
}
} else if (!strcmp(*argv,"clip")) {
set_clip = 1;
} else {
explain();
return 1;
}
argc--;
argv++;
}
s = socket(addr.sas_family, SOCK_DGRAM, 0);
if (s < 0) {
perror("socket");
return -1;
}
if (setsockopt(s, SOL_ATM, SO_ATMQOS, &qos, sizeof(qos)) < 0) {
perror("SO_ATMQOS");
return -1;
}
if (sndbuf)
if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf)) < 0) {
perror("SO_SNDBUF");
return -1;
}
if (addr.sas_family == AF_ATMSVC && setsockopt(s, SOL_ATM, SO_ATMSAP,
&sap, sizeof(sap)) < 0) {
perror("SO_ATMSAP");
return -1;
}
if (connect(s, (struct sockaddr *) &addr, addr.sas_family == AF_ATMPVC ?
sizeof(struct sockaddr_atmpvc) : sizeof(addr)) < 0) {
perror("connect");
return -1;
}
if (set_clip)
if (ioctl(s, ATMARP_MKIP, 0) < 0) {
perror("ioctl ATMARP_MKIP");
return -1;
}
tail = NLMSG_TAIL(n);
addattr_l(n, 1024, TCA_OPTIONS, NULL, 0);
addattr_l(n, 1024, TCA_ATM_FD, &s, sizeof(s));
if (excess) addattr_l(n, 1024, TCA_ATM_EXCESS, &excess, sizeof(excess));
if (hdr_len != -1) addattr_l(n, 1024, TCA_ATM_HDR, hdr, hdr_len);
tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
return 0;
}
static int atm_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
{
struct rtattr *tb[TCA_ATM_MAX+1];
char buffer[MAX_ATM_ADDR_LEN+1];
if (opt == NULL)
return 0;
parse_rtattr_nested(tb, TCA_ATM_MAX, opt);
if (tb[TCA_ATM_ADDR]) {
if (RTA_PAYLOAD(tb[TCA_ATM_ADDR]) <
sizeof(struct sockaddr_atmpvc))
fprintf(stderr, "ATM: address too short\n");
else {
if (atm2text(buffer, MAX_ATM_ADDR_LEN,
RTA_DATA(tb[TCA_ATM_ADDR]), A2T_PRETTY | A2T_NAME) <
0) fprintf(stderr, "atm2text error\n");
fprintf(f, "pvc %s ", buffer);
}
}
if (tb[TCA_ATM_HDR]) {
int i;
const __u8 *hdr = RTA_DATA(tb[TCA_ATM_HDR]);
fprintf(f, "hdr");
for (i = 0; i < RTA_PAYLOAD(tb[TCA_ATM_HDR]); i++)
fprintf(f, "%c%02x", i ? '.' : ' ', hdr[i]);
if (!i) fprintf(f, " .");
fprintf(f, " ");
}
if (tb[TCA_ATM_EXCESS]) {
__u32 excess;
if (RTA_PAYLOAD(tb[TCA_ATM_EXCESS]) < sizeof(excess))
fprintf(stderr, "ATM: excess class ID too short\n");
else {
excess = rta_getattr_u32(tb[TCA_ATM_EXCESS]);
if (!excess) fprintf(f, "excess clp ");
else {
char buf[64];
print_tc_classid(buf, sizeof(buf), excess);
fprintf(f, "excess %s ", buf);
}
}
}
if (tb[TCA_ATM_STATE]) {
static const char *map[] = { ATM_VS2TXT_MAP };
int state;
if (RTA_PAYLOAD(tb[TCA_ATM_STATE]) < sizeof(state))
fprintf(stderr, "ATM: state field too short\n");
else {
state = *(int *) RTA_DATA(tb[TCA_ATM_STATE]);
fprintf(f, "%s ", map[state]);
}
}
return 0;
}
struct qdisc_util atm_qdisc_util = {
.id = "atm",
.parse_qopt = atm_parse_opt,
.print_qopt = atm_print_opt,
.parse_copt = atm_parse_class_opt,
.print_copt = atm_print_opt,
};