/mandos/trunk

To get this branch, use:
bzr branch http://bzr.recompile.se/loggerhead/mandos/trunk

« back to all changes in this revision

Viewing changes to plugins.d/mandos-client.c

* plugins.d/mandos-client.c (good_interface): Use SIOCGIFFLAGS instead
                                              of reading
                                              /sys/class/net/*/flags.

Show diffs side-by-side

added added

removed removed

Lines of Context:
26
26
 * along with this program.  If not, see
27
27
 * <http://www.gnu.org/licenses/>.
28
28
 * 
29
 
 * Contact the authors at <mandos@fukt.bsnet.se>.
 
29
 * Contact the authors at <mandos@recompile.se>.
30
30
 */
31
31
 
32
32
/* Needed by GPGME, specifically gpgme_data_seek() */
127
127
bool debug = false;
128
128
static const char mandos_protocol_version[] = "1";
129
129
const char *argp_program_version = "mandos-client " VERSION;
130
 
const char *argp_program_bug_address = "<mandos@fukt.bsnet.se>";
 
130
const char *argp_program_bug_address = "<mandos@recompile.se>";
131
131
static const char sys_class_net[] = "/sys/class/net";
132
132
char *connect_to = NULL;
133
133
 
1085
1085
  errno = old_errno;
1086
1086
}
1087
1087
 
1088
 
/* 
1089
 
 * This function determines if a directory entry in /sys/class/net
1090
 
 * corresponds to an acceptable network device.
1091
 
 * (This function is passed to scandir(3) as a filter function.)
1092
 
 */
1093
 
int good_interface(const struct dirent *if_entry){
1094
 
  ssize_t ssret;
1095
 
  char *flagname = NULL;
1096
 
  if(if_entry->d_name[0] == '.'){
1097
 
    return 0;
1098
 
  }
1099
 
  int ret = asprintf(&flagname, "%s/%s/flags", sys_class_net,
1100
 
                     if_entry->d_name);
1101
 
  if(ret < 0){
1102
 
    perror_plus("asprintf");
1103
 
    return 0;
1104
 
  }
1105
 
  int flags_fd = (int)TEMP_FAILURE_RETRY(open(flagname, O_RDONLY));
1106
 
  if(flags_fd == -1){
1107
 
    perror_plus("open");
1108
 
    free(flagname);
1109
 
    return 0;
1110
 
  }
1111
 
  free(flagname);
1112
 
  typedef short ifreq_flags;    /* ifreq.ifr_flags in netdevice(7) */
1113
 
  /* read line from flags_fd */
1114
 
  ssize_t to_read = 2+(sizeof(ifreq_flags)*2)+1; /* "0x1003\n" */
1115
 
  char *flagstring = malloc((size_t)to_read+1); /* +1 for final \0 */
1116
 
  flagstring[(size_t)to_read] = '\0';
1117
 
  if(flagstring == NULL){
1118
 
    perror_plus("malloc");
1119
 
    close(flags_fd);
1120
 
    return 0;
1121
 
  }
1122
 
  while(to_read > 0){
1123
 
    ssret = (ssize_t)TEMP_FAILURE_RETRY(read(flags_fd, flagstring,
1124
 
                                             (size_t)to_read));
1125
 
    if(ssret == -1){
1126
 
      perror_plus("read");
1127
 
      free(flagstring);
1128
 
      close(flags_fd);
1129
 
      return 0;
1130
 
    }
1131
 
    to_read -= ssret;
1132
 
    if(ssret == 0){
1133
 
      break;
1134
 
    }
1135
 
  }
1136
 
  close(flags_fd);
1137
 
  intmax_t tmpmax;
1138
 
  char *tmp;
1139
 
  errno = 0;
1140
 
  tmpmax = strtoimax(flagstring, &tmp, 0);
1141
 
  if(errno != 0 or tmp == flagstring or (*tmp != '\0'
1142
 
                                         and not (isspace(*tmp)))
1143
 
     or tmpmax != (ifreq_flags)tmpmax){
 
1088
bool get_flags(const char *ifname, struct ifreq *ifr){
 
1089
  int ret;
 
1090
  
 
1091
  int s = socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP);
 
1092
  if(s < 0){
 
1093
    perror_plus("socket");
 
1094
    return false;
 
1095
  }
 
1096
  strcpy(ifr->ifr_name, ifname);
 
1097
  ret = ioctl(s, SIOCGIFFLAGS, ifr);
 
1098
  if(ret == -1){
1144
1099
    if(debug){
1145
 
      fprintf(stderr, "Invalid flags \"%s\" for interface \"%s\"\n",
1146
 
              flagstring, if_entry->d_name);
 
1100
      perror_plus("ioctl SIOCGIFFLAGS");
1147
1101
    }
1148
 
    free(flagstring);
1149
 
    return 0;
 
1102
    return false;
1150
1103
  }
1151
 
  free(flagstring);
1152
 
  ifreq_flags flags = (ifreq_flags)tmpmax;
 
1104
  return true;
 
1105
}
 
1106
 
 
1107
bool good_flags(const char *ifname, const struct ifreq *ifr){
 
1108
  
1153
1109
  /* Reject the loopback device */
1154
 
  if(flags & IFF_LOOPBACK){
 
1110
  if(ifr->ifr_flags & IFF_LOOPBACK){
1155
1111
    if(debug){
1156
1112
      fprintf(stderr, "Rejecting loopback interface \"%s\"\n",
1157
 
              if_entry->d_name);
 
1113
              ifname);
1158
1114
    }
1159
 
    return 0;
 
1115
    return false;
1160
1116
  }
1161
1117
  /* Accept point-to-point devices only if connect_to is specified */
1162
 
  if(connect_to != NULL and (flags & IFF_POINTOPOINT)){
 
1118
  if(connect_to != NULL and (ifr->ifr_flags & IFF_POINTOPOINT)){
1163
1119
    if(debug){
1164
1120
      fprintf(stderr, "Accepting point-to-point interface \"%s\"\n",
1165
 
              if_entry->d_name);
 
1121
              ifname);
1166
1122
    }
1167
 
    return 1;
 
1123
    return true;
1168
1124
  }
1169
1125
  /* Otherwise, reject non-broadcast-capable devices */
1170
 
  if(not (flags & IFF_BROADCAST)){
 
1126
  if(not (ifr->ifr_flags & IFF_BROADCAST)){
1171
1127
    if(debug){
1172
1128
      fprintf(stderr, "Rejecting non-broadcast interface \"%s\"\n",
1173
 
              if_entry->d_name);
 
1129
              ifname);
1174
1130
    }
1175
 
    return 0;
 
1131
    return false;
1176
1132
  }
1177
1133
  /* Reject non-ARP interfaces (including dummy interfaces) */
1178
 
  if(flags & IFF_NOARP){
 
1134
  if(ifr->ifr_flags & IFF_NOARP){
1179
1135
    if(debug){
1180
 
      fprintf(stderr, "Rejecting non-ARP interface \"%s\"\n",
1181
 
              if_entry->d_name);
 
1136
      fprintf(stderr, "Rejecting non-ARP interface \"%s\"\n", ifname);
1182
1137
    }
1183
 
    return 0;
 
1138
    return false;
1184
1139
  }
 
1140
  
1185
1141
  /* Accept this device */
1186
1142
  if(debug){
1187
 
    fprintf(stderr, "Interface \"%s\" is acceptable\n",
1188
 
            if_entry->d_name);
 
1143
    fprintf(stderr, "Interface \"%s\" is good\n", ifname);
 
1144
  }
 
1145
  return true;
 
1146
}
 
1147
 
 
1148
/* 
 
1149
 * This function determines if a directory entry in /sys/class/net
 
1150
 * corresponds to an acceptable network device.
 
1151
 * (This function is passed to scandir(3) as a filter function.)
 
1152
 */
 
1153
int good_interface(const struct dirent *if_entry){
 
1154
  int ret;
 
1155
  if(if_entry->d_name[0] == '.'){
 
1156
    return 0;
 
1157
  }
 
1158
  struct ifreq ifr;
 
1159
 
 
1160
  if(not get_flags(if_entry->d_name, &ifr)){
 
1161
    return 0;
 
1162
  }
 
1163
  
 
1164
  if(not good_flags(if_entry->d_name, &ifr)){
 
1165
    return 0;
1189
1166
  }
1190
1167
  return 1;
1191
1168
}