diff options
Diffstat (limited to 'src/ipcpd/normal')
-rw-r--r-- | src/ipcpd/normal/pol/link_state.c | 109 |
1 files changed, 80 insertions, 29 deletions
diff --git a/src/ipcpd/normal/pol/link_state.c b/src/ipcpd/normal/pol/link_state.c index 520e2952..179a3448 100644 --- a/src/ipcpd/normal/pol/link_state.c +++ b/src/ipcpd/normal/pol/link_state.c @@ -52,6 +52,7 @@ #define RECALC_TIME 4 #define LS_UPDATE_TIME 15 #define LS_TIMEO 60 +#define LS_ENTRY_SIZE 78 #define LSDB "lsdb" #ifndef CLOCK_REALTIME_COARSE @@ -131,51 +132,96 @@ static int str_adj(struct adjacency * adj, size_t len) { char tmbuf[64]; + char srcbuf[64]; + char dstbuf[64]; struct tm * tm; - if (len < 256) + if (len < LS_ENTRY_SIZE) return -1; tm = localtime(&adj->stamp); - strftime(tmbuf, sizeof(tmbuf), "%Y-%m-%d %H:%M:%S", tm); + strftime(tmbuf, sizeof(tmbuf), "%F %T", tm); /* 19 chars */ - sprintf(buf, - "src: %" PRIu64 "\n" - "dst: %" PRIu64 "\n" - "upd: %s\n", - adj->src, - adj->dst, - tmbuf); + sprintf(srcbuf, "%" PRIu64, adj->src); + sprintf(dstbuf, "%" PRIu64, adj->dst); - return strlen(buf); + sprintf(buf, "src: %20s\ndst: %20s\nupd: %20s\n", + srcbuf, dstbuf, tmbuf); + + return LS_ENTRY_SIZE; } -static int lsdb_read(const char * path, - char * buf, - size_t len) +static struct adjacency * get_adj(const char * path) { struct list_head * p; char entry[RIB_PATH_LEN + 1]; - pthread_rwlock_rdlock(&ls.db_lock); - - if (ls.db_len + ls.nbs_len == 0) { - pthread_rwlock_unlock(&ls.db_lock); - return -EPERM; - } + assert(path); list_for_each(p, &ls.db) { struct adjacency * a = list_entry(p, struct adjacency, next); sprintf(entry, "%" PRIu64 ".%" PRIu64, a->src, a->dst); - if (strcmp(entry, path) == 0) { - len = str_adj(a, buf, len); - pthread_rwlock_unlock(&ls.db_lock); - return len; - } + if (strcmp(entry, path) == 0) + return a; + } + + return NULL; +} + +static int lsdb_getattr(const char * path, + struct stat * st) +{ + struct adjacency * adj; + struct timespec now; + + clock_gettime(CLOCK_REALTIME_COARSE, &now); + + pthread_rwlock_rdlock(&ls.db_lock); + + adj = get_adj(path); + if (adj != NULL) { + st->st_mtime = adj->stamp; + st->st_size = LS_ENTRY_SIZE; + } else { + st->st_mtime = now.tv_sec; + st->st_size = 0; } + st->st_mode = S_IFREG | 0755; + st->st_nlink = 1; + st->st_uid = getuid(); + st->st_gid = getgid(); + + pthread_rwlock_unlock(&ls.db_lock); + + return 0; +} + +static int lsdb_read(const char * path, + char * buf, + size_t len) +{ + struct adjacency * a; + int size; + + pthread_rwlock_rdlock(&ls.db_lock); + + if (ls.db_len + ls.nbs_len == 0) + goto fail; + + a = get_adj(path); + if (a == NULL) + goto fail; + + size = str_adj(a, buf, len); + if (size < 0) + goto fail; + pthread_rwlock_unlock(&ls.db_lock); + return size; + fail: + pthread_rwlock_unlock(&ls.db_lock); return -1; } @@ -204,8 +250,8 @@ static int lsdb_readdir(char *** buf) sprintf(entry, "%s%" PRIu64, str, nb->addr); (*buf)[idx] = malloc(strlen(entry) + 1); if ((*buf)[idx] == NULL) { - while (--idx >= 0) - free(*buf[idx]); + while (idx-- > 0) + free((*buf)[idx]); free(buf); pthread_rwlock_unlock(&ls.db_lock); return -ENOMEM; @@ -241,7 +287,8 @@ static int lsdb_readdir(char *** buf) static struct rib_ops r_ops = { .read = lsdb_read, - .readdir = lsdb_readdir + .readdir = lsdb_readdir, + .getattr = lsdb_getattr }; static int lsdb_add_nb(uint64_t addr, @@ -801,13 +848,17 @@ int link_state_init(enum pol_routing pr) if (pthread_create(&ls.listener, NULL, ls_conn_handle, NULL)) goto fail_pthread_create_listener; + if (rib_reg(LSDB, &r_ops)) + goto fail_rib_reg; + ls.db_len = 0; ls.nbs_len = 0; - rib_reg(LSDB, &r_ops); - return 0; + fail_rib_reg: + pthread_cancel(ls.listener); + pthread_join(ls.listener, NULL); fail_pthread_create_listener: pthread_cancel(ls.lsreader); pthread_join(ls.lsreader, NULL); |