p2p_utils.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522
  1. /*
  2. * P2P - generic helper functions
  3. * Copyright (c) 2009, Atheros Communications
  4. *
  5. * This software may be distributed under the terms of the BSD license.
  6. * See README for more details.
  7. */
  8. #include "includes.h"
  9. #include "common.h"
  10. #include "common/ieee802_11_common.h"
  11. #include "p2p_i.h"
  12. /**
  13. * p2p_random - Generate random string for SSID and passphrase
  14. * @buf: Buffer for returning the result
  15. * @len: Number of octets to write to the buffer
  16. * Returns: 0 on success, -1 on failure
  17. *
  18. * This function generates a random string using the following character set:
  19. * 'A'-'Z', 'a'-'z', '0'-'9'.
  20. */
  21. int p2p_random(char *buf, size_t len)
  22. {
  23. u8 val;
  24. size_t i;
  25. u8 letters = 'Z' - 'A' + 1;
  26. u8 numbers = 10;
  27. if (os_get_random((unsigned char *) buf, len))
  28. return -1;
  29. /* Character set: 'A'-'Z', 'a'-'z', '0'-'9' */
  30. for (i = 0; i < len; i++) {
  31. val = buf[i];
  32. val %= 2 * letters + numbers;
  33. if (val < letters)
  34. buf[i] = 'A' + val;
  35. else if (val < 2 * letters)
  36. buf[i] = 'a' + (val - letters);
  37. else
  38. buf[i] = '0' + (val - 2 * letters);
  39. }
  40. return 0;
  41. }
  42. /**
  43. * p2p_channel_to_freq - Convert channel info to frequency
  44. * @op_class: Operating class
  45. * @channel: Channel number
  46. * Returns: Frequency in MHz or -1 if the specified channel is unknown
  47. */
  48. int p2p_channel_to_freq(int op_class, int channel)
  49. {
  50. return ieee80211_chan_to_freq(NULL, op_class, channel);
  51. }
  52. /**
  53. * p2p_freq_to_channel - Convert frequency into channel info
  54. * @op_class: Buffer for returning operating class
  55. * @channel: Buffer for returning channel number
  56. * Returns: 0 on success, -1 if the specified frequency is unknown
  57. */
  58. int p2p_freq_to_channel(unsigned int freq, u8 *op_class, u8 *channel)
  59. {
  60. /* TODO: more operating classes */
  61. if (freq >= 2412 && freq <= 2472) {
  62. if ((freq - 2407) % 5)
  63. return -1;
  64. *op_class = 81; /* 2.407 GHz, channels 1..13 */
  65. *channel = (freq - 2407) / 5;
  66. return 0;
  67. }
  68. if (freq == 2484) {
  69. *op_class = 82; /* channel 14 */
  70. *channel = 14;
  71. return 0;
  72. }
  73. if (freq >= 5180 && freq <= 5240) {
  74. if ((freq - 5000) % 5)
  75. return -1;
  76. *op_class = 115; /* 5 GHz, channels 36..48 */
  77. *channel = (freq - 5000) / 5;
  78. return 0;
  79. }
  80. if (freq >= 5745 && freq <= 5805) {
  81. if ((freq - 5000) % 5)
  82. return -1;
  83. *op_class = 124; /* 5 GHz, channels 149..161 */
  84. *channel = (freq - 5000) / 5;
  85. return 0;
  86. }
  87. if (freq >= 5745 && freq <= 5845) {
  88. if ((freq - 5000) % 5)
  89. return -1;
  90. *op_class = 125; /* 5 GHz, channels 149..169 */
  91. *channel = (freq - 5000) / 5;
  92. return 0;
  93. }
  94. if (freq >= 58320 && freq <= 64800) {
  95. if ((freq - 58320) % 2160)
  96. return -1;
  97. *op_class = 180; /* 60 GHz, channels 1..4 */
  98. *channel = (freq - 56160) / 2160;
  99. return 0;
  100. }
  101. return -1;
  102. }
  103. static void p2p_reg_class_intersect(const struct p2p_reg_class *a,
  104. const struct p2p_reg_class *b,
  105. struct p2p_reg_class *res)
  106. {
  107. size_t i, j;
  108. res->reg_class = a->reg_class;
  109. for (i = 0; i < a->channels; i++) {
  110. for (j = 0; j < b->channels; j++) {
  111. if (a->channel[i] != b->channel[j])
  112. continue;
  113. res->channel[res->channels] = a->channel[i];
  114. res->channels++;
  115. if (res->channels == P2P_MAX_REG_CLASS_CHANNELS)
  116. return;
  117. }
  118. }
  119. }
  120. /**
  121. * p2p_channels_intersect - Intersection of supported channel lists
  122. * @a: First set of supported channels
  123. * @b: Second set of supported channels
  124. * @res: Data structure for returning the intersection of support channels
  125. *
  126. * This function can be used to find a common set of supported channels. Both
  127. * input channels sets are assumed to use the same country code. If different
  128. * country codes are used, the regulatory class numbers may not be matched
  129. * correctly and results are undefined.
  130. */
  131. void p2p_channels_intersect(const struct p2p_channels *a,
  132. const struct p2p_channels *b,
  133. struct p2p_channels *res)
  134. {
  135. size_t i, j;
  136. os_memset(res, 0, sizeof(*res));
  137. for (i = 0; i < a->reg_classes; i++) {
  138. const struct p2p_reg_class *a_reg = &a->reg_class[i];
  139. for (j = 0; j < b->reg_classes; j++) {
  140. const struct p2p_reg_class *b_reg = &b->reg_class[j];
  141. if (a_reg->reg_class != b_reg->reg_class)
  142. continue;
  143. p2p_reg_class_intersect(
  144. a_reg, b_reg,
  145. &res->reg_class[res->reg_classes]);
  146. if (res->reg_class[res->reg_classes].channels) {
  147. res->reg_classes++;
  148. if (res->reg_classes == P2P_MAX_REG_CLASSES)
  149. return;
  150. }
  151. }
  152. }
  153. }
  154. static void p2p_op_class_union(struct p2p_reg_class *cl,
  155. const struct p2p_reg_class *b_cl)
  156. {
  157. size_t i, j;
  158. for (i = 0; i < b_cl->channels; i++) {
  159. for (j = 0; j < cl->channels; j++) {
  160. if (b_cl->channel[i] == cl->channel[j])
  161. break;
  162. }
  163. if (j == cl->channels) {
  164. if (cl->channels == P2P_MAX_REG_CLASS_CHANNELS)
  165. return;
  166. cl->channel[cl->channels++] = b_cl->channel[i];
  167. }
  168. }
  169. }
  170. /**
  171. * p2p_channels_union_inplace - Inplace union of channel lists
  172. * @res: Input data and place for returning union of the channel sets
  173. * @b: Second set of channels
  174. */
  175. void p2p_channels_union_inplace(struct p2p_channels *res,
  176. const struct p2p_channels *b)
  177. {
  178. size_t i, j;
  179. for (i = 0; i < res->reg_classes; i++) {
  180. struct p2p_reg_class *cl = &res->reg_class[i];
  181. for (j = 0; j < b->reg_classes; j++) {
  182. const struct p2p_reg_class *b_cl = &b->reg_class[j];
  183. if (cl->reg_class != b_cl->reg_class)
  184. continue;
  185. p2p_op_class_union(cl, b_cl);
  186. }
  187. }
  188. for (j = 0; j < b->reg_classes; j++) {
  189. const struct p2p_reg_class *b_cl = &b->reg_class[j];
  190. for (i = 0; i < res->reg_classes; i++) {
  191. struct p2p_reg_class *cl = &res->reg_class[i];
  192. if (cl->reg_class == b_cl->reg_class)
  193. break;
  194. }
  195. if (i == res->reg_classes) {
  196. if (res->reg_classes == P2P_MAX_REG_CLASSES)
  197. return;
  198. os_memcpy(&res->reg_class[res->reg_classes++],
  199. b_cl, sizeof(struct p2p_reg_class));
  200. }
  201. }
  202. }
  203. /**
  204. * p2p_channels_union - Union of channel lists
  205. * @a: First set of channels
  206. * @b: Second set of channels
  207. * @res: Data structure for returning the union of channels
  208. */
  209. void p2p_channels_union(const struct p2p_channels *a,
  210. const struct p2p_channels *b,
  211. struct p2p_channels *res)
  212. {
  213. os_memcpy(res, a, sizeof(*res));
  214. p2p_channels_union_inplace(res, b);
  215. }
  216. void p2p_channels_remove_freqs(struct p2p_channels *chan,
  217. const struct wpa_freq_range_list *list)
  218. {
  219. size_t o, c;
  220. if (list == NULL)
  221. return;
  222. o = 0;
  223. while (o < chan->reg_classes) {
  224. struct p2p_reg_class *op = &chan->reg_class[o];
  225. c = 0;
  226. while (c < op->channels) {
  227. int freq = p2p_channel_to_freq(op->reg_class,
  228. op->channel[c]);
  229. if (freq > 0 && freq_range_list_includes(list, freq)) {
  230. op->channels--;
  231. os_memmove(&op->channel[c],
  232. &op->channel[c + 1],
  233. op->channels - c);
  234. } else
  235. c++;
  236. }
  237. if (op->channels == 0) {
  238. chan->reg_classes--;
  239. os_memmove(&chan->reg_class[o], &chan->reg_class[o + 1],
  240. (chan->reg_classes - o) *
  241. sizeof(struct p2p_reg_class));
  242. } else
  243. o++;
  244. }
  245. }
  246. /**
  247. * p2p_channels_includes - Check whether a channel is included in the list
  248. * @channels: List of supported channels
  249. * @reg_class: Regulatory class of the channel to search
  250. * @channel: Channel number of the channel to search
  251. * Returns: 1 if channel was found or 0 if not
  252. */
  253. int p2p_channels_includes(const struct p2p_channels *channels, u8 reg_class,
  254. u8 channel)
  255. {
  256. size_t i, j;
  257. for (i = 0; i < channels->reg_classes; i++) {
  258. const struct p2p_reg_class *reg = &channels->reg_class[i];
  259. if (reg->reg_class != reg_class)
  260. continue;
  261. for (j = 0; j < reg->channels; j++) {
  262. if (reg->channel[j] == channel)
  263. return 1;
  264. }
  265. }
  266. return 0;
  267. }
  268. int p2p_channels_includes_freq(const struct p2p_channels *channels,
  269. unsigned int freq)
  270. {
  271. size_t i, j;
  272. for (i = 0; i < channels->reg_classes; i++) {
  273. const struct p2p_reg_class *reg = &channels->reg_class[i];
  274. for (j = 0; j < reg->channels; j++) {
  275. if (p2p_channel_to_freq(reg->reg_class,
  276. reg->channel[j]) == (int) freq)
  277. return 1;
  278. }
  279. }
  280. return 0;
  281. }
  282. int p2p_supported_freq(struct p2p_data *p2p, unsigned int freq)
  283. {
  284. u8 op_reg_class, op_channel;
  285. if (p2p_freq_to_channel(freq, &op_reg_class, &op_channel) < 0)
  286. return 0;
  287. return p2p_channels_includes(&p2p->cfg->channels, op_reg_class,
  288. op_channel);
  289. }
  290. int p2p_supported_freq_go(struct p2p_data *p2p, unsigned int freq)
  291. {
  292. u8 op_reg_class, op_channel;
  293. if (p2p_freq_to_channel(freq, &op_reg_class, &op_channel) < 0)
  294. return 0;
  295. return p2p_channels_includes(&p2p->cfg->channels, op_reg_class,
  296. op_channel) &&
  297. !freq_range_list_includes(&p2p->no_go_freq, freq);
  298. }
  299. int p2p_supported_freq_cli(struct p2p_data *p2p, unsigned int freq)
  300. {
  301. u8 op_reg_class, op_channel;
  302. if (p2p_freq_to_channel(freq, &op_reg_class, &op_channel) < 0)
  303. return 0;
  304. return p2p_channels_includes(&p2p->cfg->channels, op_reg_class,
  305. op_channel) ||
  306. p2p_channels_includes(&p2p->cfg->cli_channels, op_reg_class,
  307. op_channel);
  308. }
  309. unsigned int p2p_get_pref_freq(struct p2p_data *p2p,
  310. const struct p2p_channels *channels)
  311. {
  312. unsigned int i;
  313. int freq = 0;
  314. const struct p2p_channels *tmpc = channels ?
  315. channels : &p2p->cfg->channels;
  316. if (tmpc == NULL)
  317. return 0;
  318. for (i = 0; p2p->cfg->pref_chan && i < p2p->cfg->num_pref_chan; i++) {
  319. freq = p2p_channel_to_freq(p2p->cfg->pref_chan[i].op_class,
  320. p2p->cfg->pref_chan[i].chan);
  321. if (p2p_channels_includes_freq(tmpc, freq))
  322. return freq;
  323. }
  324. return 0;
  325. }
  326. void p2p_channels_dump(struct p2p_data *p2p, const char *title,
  327. const struct p2p_channels *chan)
  328. {
  329. char buf[500], *pos, *end;
  330. size_t i, j;
  331. int ret;
  332. pos = buf;
  333. end = pos + sizeof(buf);
  334. for (i = 0; i < chan->reg_classes; i++) {
  335. const struct p2p_reg_class *c;
  336. c = &chan->reg_class[i];
  337. ret = os_snprintf(pos, end - pos, " %u:", c->reg_class);
  338. if (os_snprintf_error(end - pos, ret))
  339. break;
  340. pos += ret;
  341. for (j = 0; j < c->channels; j++) {
  342. ret = os_snprintf(pos, end - pos, "%s%u",
  343. j == 0 ? "" : ",",
  344. c->channel[j]);
  345. if (os_snprintf_error(end - pos, ret))
  346. break;
  347. pos += ret;
  348. }
  349. }
  350. *pos = '\0';
  351. p2p_dbg(p2p, "%s:%s", title, buf);
  352. }
  353. static u8 p2p_channel_pick_random(const u8 *channels, unsigned int num_channels)
  354. {
  355. unsigned int r;
  356. if (os_get_random((u8 *) &r, sizeof(r)) < 0)
  357. r = 0;
  358. r %= num_channels;
  359. return channels[r];
  360. }
  361. int p2p_channel_select(struct p2p_channels *chans, const int *classes,
  362. u8 *op_class, u8 *op_channel)
  363. {
  364. unsigned int i, j;
  365. for (j = 0; classes == NULL || classes[j]; j++) {
  366. for (i = 0; i < chans->reg_classes; i++) {
  367. struct p2p_reg_class *c = &chans->reg_class[i];
  368. if (c->channels == 0)
  369. continue;
  370. if (classes == NULL || c->reg_class == classes[j]) {
  371. /*
  372. * Pick one of the available channels in the
  373. * operating class at random.
  374. */
  375. *op_class = c->reg_class;
  376. *op_channel = p2p_channel_pick_random(
  377. c->channel, c->channels);
  378. return 0;
  379. }
  380. }
  381. if (classes == NULL)
  382. break;
  383. }
  384. return -1;
  385. }
  386. int p2p_channel_random_social(struct p2p_channels *chans, u8 *op_class,
  387. u8 *op_channel)
  388. {
  389. u8 chan[4];
  390. unsigned int num_channels = 0;
  391. /* Try to find available social channels from 2.4 GHz */
  392. if (p2p_channels_includes(chans, 81, 1))
  393. chan[num_channels++] = 1;
  394. if (p2p_channels_includes(chans, 81, 6))
  395. chan[num_channels++] = 6;
  396. if (p2p_channels_includes(chans, 81, 11))
  397. chan[num_channels++] = 11;
  398. /* Try to find available social channels from 60 GHz */
  399. if (p2p_channels_includes(chans, 180, 2))
  400. chan[num_channels++] = 2;
  401. if (num_channels == 0)
  402. return -1;
  403. *op_channel = p2p_channel_pick_random(chan, num_channels);
  404. if (*op_channel == 2)
  405. *op_class = 180;
  406. else
  407. *op_class = 81;
  408. return 0;
  409. }
  410. int p2p_channels_to_freqs(const struct p2p_channels *channels, int *freq_list,
  411. unsigned int max_len)
  412. {
  413. unsigned int i, idx;
  414. if (!channels || max_len == 0)
  415. return 0;
  416. for (i = 0, idx = 0; i < channels->reg_classes; i++) {
  417. const struct p2p_reg_class *c = &channels->reg_class[i];
  418. unsigned int j;
  419. if (idx + 1 == max_len)
  420. break;
  421. for (j = 0; j < c->channels; j++) {
  422. int freq;
  423. if (idx + 1 == max_len)
  424. break;
  425. freq = p2p_channel_to_freq(c->reg_class,
  426. c->channel[j]);
  427. if (freq < 0)
  428. continue;
  429. freq_list[idx++] = freq;
  430. }
  431. }
  432. freq_list[idx] = 0;
  433. return idx;
  434. }