gen.go 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387
  1. // Copyright 2013 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. // +build ignore
  5. //go:generate go run gen.go
  6. // This program generates internet protocol constants and tables by
  7. // reading IANA protocol registries.
  8. package main
  9. import (
  10. "bytes"
  11. "encoding/xml"
  12. "fmt"
  13. "go/format"
  14. "io"
  15. "io/ioutil"
  16. "net/http"
  17. "os"
  18. "strconv"
  19. "strings"
  20. )
  21. var registries = []struct {
  22. url string
  23. parse func(io.Writer, io.Reader) error
  24. }{
  25. {
  26. "https://www.iana.org/assignments/dscp-registry/dscp-registry.xml",
  27. parseDSCPRegistry,
  28. },
  29. {
  30. "https://www.iana.org/assignments/ipv4-tos-byte/ipv4-tos-byte.xml",
  31. parseTOSTCByte,
  32. },
  33. {
  34. "https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xml",
  35. parseProtocolNumbers,
  36. },
  37. {
  38. "http://www.iana.org/assignments/address-family-numbers/address-family-numbers.xml",
  39. parseAddrFamilyNumbers,
  40. },
  41. }
  42. func main() {
  43. var bb bytes.Buffer
  44. fmt.Fprintf(&bb, "// go generate gen.go\n")
  45. fmt.Fprintf(&bb, "// Code generated by the command above; DO NOT EDIT.\n\n")
  46. fmt.Fprintf(&bb, "// Package iana provides protocol number resources managed by the Internet Assigned Numbers Authority (IANA).\n")
  47. fmt.Fprintf(&bb, `package iana // import "golang.org/x/net/internal/iana"`+"\n\n")
  48. for _, r := range registries {
  49. resp, err := http.Get(r.url)
  50. if err != nil {
  51. fmt.Fprintln(os.Stderr, err)
  52. os.Exit(1)
  53. }
  54. defer resp.Body.Close()
  55. if resp.StatusCode != http.StatusOK {
  56. fmt.Fprintf(os.Stderr, "got HTTP status code %v for %v\n", resp.StatusCode, r.url)
  57. os.Exit(1)
  58. }
  59. if err := r.parse(&bb, resp.Body); err != nil {
  60. fmt.Fprintln(os.Stderr, err)
  61. os.Exit(1)
  62. }
  63. fmt.Fprintf(&bb, "\n")
  64. }
  65. b, err := format.Source(bb.Bytes())
  66. if err != nil {
  67. fmt.Fprintln(os.Stderr, err)
  68. os.Exit(1)
  69. }
  70. if err := ioutil.WriteFile("const.go", b, 0644); err != nil {
  71. fmt.Fprintln(os.Stderr, err)
  72. os.Exit(1)
  73. }
  74. }
  75. func parseDSCPRegistry(w io.Writer, r io.Reader) error {
  76. dec := xml.NewDecoder(r)
  77. var dr dscpRegistry
  78. if err := dec.Decode(&dr); err != nil {
  79. return err
  80. }
  81. drs := dr.escape()
  82. fmt.Fprintf(w, "// %s, Updated: %s\n", dr.Title, dr.Updated)
  83. fmt.Fprintf(w, "const (\n")
  84. for _, dr := range drs {
  85. fmt.Fprintf(w, "DiffServ%s = %#x", dr.Name, dr.Value)
  86. fmt.Fprintf(w, "// %s\n", dr.OrigName)
  87. }
  88. fmt.Fprintf(w, ")\n")
  89. return nil
  90. }
  91. type dscpRegistry struct {
  92. XMLName xml.Name `xml:"registry"`
  93. Title string `xml:"title"`
  94. Updated string `xml:"updated"`
  95. Note string `xml:"note"`
  96. RegTitle string `xml:"registry>title"`
  97. PoolRecords []struct {
  98. Name string `xml:"name"`
  99. Space string `xml:"space"`
  100. } `xml:"registry>record"`
  101. Records []struct {
  102. Name string `xml:"name"`
  103. Space string `xml:"space"`
  104. } `xml:"registry>registry>record"`
  105. }
  106. type canonDSCPRecord struct {
  107. OrigName string
  108. Name string
  109. Value int
  110. }
  111. func (drr *dscpRegistry) escape() []canonDSCPRecord {
  112. drs := make([]canonDSCPRecord, len(drr.Records))
  113. sr := strings.NewReplacer(
  114. "+", "",
  115. "-", "",
  116. "/", "",
  117. ".", "",
  118. " ", "",
  119. )
  120. for i, dr := range drr.Records {
  121. s := strings.TrimSpace(dr.Name)
  122. drs[i].OrigName = s
  123. drs[i].Name = sr.Replace(s)
  124. n, err := strconv.ParseUint(dr.Space, 2, 8)
  125. if err != nil {
  126. continue
  127. }
  128. drs[i].Value = int(n) << 2
  129. }
  130. return drs
  131. }
  132. func parseTOSTCByte(w io.Writer, r io.Reader) error {
  133. dec := xml.NewDecoder(r)
  134. var ttb tosTCByte
  135. if err := dec.Decode(&ttb); err != nil {
  136. return err
  137. }
  138. trs := ttb.escape()
  139. fmt.Fprintf(w, "// %s, Updated: %s\n", ttb.Title, ttb.Updated)
  140. fmt.Fprintf(w, "const (\n")
  141. for _, tr := range trs {
  142. fmt.Fprintf(w, "%s = %#x", tr.Keyword, tr.Value)
  143. fmt.Fprintf(w, "// %s\n", tr.OrigKeyword)
  144. }
  145. fmt.Fprintf(w, ")\n")
  146. return nil
  147. }
  148. type tosTCByte struct {
  149. XMLName xml.Name `xml:"registry"`
  150. Title string `xml:"title"`
  151. Updated string `xml:"updated"`
  152. Note string `xml:"note"`
  153. RegTitle string `xml:"registry>title"`
  154. Records []struct {
  155. Binary string `xml:"binary"`
  156. Keyword string `xml:"keyword"`
  157. } `xml:"registry>record"`
  158. }
  159. type canonTOSTCByteRecord struct {
  160. OrigKeyword string
  161. Keyword string
  162. Value int
  163. }
  164. func (ttb *tosTCByte) escape() []canonTOSTCByteRecord {
  165. trs := make([]canonTOSTCByteRecord, len(ttb.Records))
  166. sr := strings.NewReplacer(
  167. "Capable", "",
  168. "(", "",
  169. ")", "",
  170. "+", "",
  171. "-", "",
  172. "/", "",
  173. ".", "",
  174. " ", "",
  175. )
  176. for i, tr := range ttb.Records {
  177. s := strings.TrimSpace(tr.Keyword)
  178. trs[i].OrigKeyword = s
  179. ss := strings.Split(s, " ")
  180. if len(ss) > 1 {
  181. trs[i].Keyword = strings.Join(ss[1:], " ")
  182. } else {
  183. trs[i].Keyword = ss[0]
  184. }
  185. trs[i].Keyword = sr.Replace(trs[i].Keyword)
  186. n, err := strconv.ParseUint(tr.Binary, 2, 8)
  187. if err != nil {
  188. continue
  189. }
  190. trs[i].Value = int(n)
  191. }
  192. return trs
  193. }
  194. func parseProtocolNumbers(w io.Writer, r io.Reader) error {
  195. dec := xml.NewDecoder(r)
  196. var pn protocolNumbers
  197. if err := dec.Decode(&pn); err != nil {
  198. return err
  199. }
  200. prs := pn.escape()
  201. prs = append([]canonProtocolRecord{{
  202. Name: "IP",
  203. Descr: "IPv4 encapsulation, pseudo protocol number",
  204. Value: 0,
  205. }}, prs...)
  206. fmt.Fprintf(w, "// %s, Updated: %s\n", pn.Title, pn.Updated)
  207. fmt.Fprintf(w, "const (\n")
  208. for _, pr := range prs {
  209. if pr.Name == "" {
  210. continue
  211. }
  212. fmt.Fprintf(w, "Protocol%s = %d", pr.Name, pr.Value)
  213. s := pr.Descr
  214. if s == "" {
  215. s = pr.OrigName
  216. }
  217. fmt.Fprintf(w, "// %s\n", s)
  218. }
  219. fmt.Fprintf(w, ")\n")
  220. return nil
  221. }
  222. type protocolNumbers struct {
  223. XMLName xml.Name `xml:"registry"`
  224. Title string `xml:"title"`
  225. Updated string `xml:"updated"`
  226. RegTitle string `xml:"registry>title"`
  227. Note string `xml:"registry>note"`
  228. Records []struct {
  229. Value string `xml:"value"`
  230. Name string `xml:"name"`
  231. Descr string `xml:"description"`
  232. } `xml:"registry>record"`
  233. }
  234. type canonProtocolRecord struct {
  235. OrigName string
  236. Name string
  237. Descr string
  238. Value int
  239. }
  240. func (pn *protocolNumbers) escape() []canonProtocolRecord {
  241. prs := make([]canonProtocolRecord, len(pn.Records))
  242. sr := strings.NewReplacer(
  243. "-in-", "in",
  244. "-within-", "within",
  245. "-over-", "over",
  246. "+", "P",
  247. "-", "",
  248. "/", "",
  249. ".", "",
  250. " ", "",
  251. )
  252. for i, pr := range pn.Records {
  253. if strings.Contains(pr.Name, "Deprecated") ||
  254. strings.Contains(pr.Name, "deprecated") {
  255. continue
  256. }
  257. prs[i].OrigName = pr.Name
  258. s := strings.TrimSpace(pr.Name)
  259. switch pr.Name {
  260. case "ISIS over IPv4":
  261. prs[i].Name = "ISIS"
  262. case "manet":
  263. prs[i].Name = "MANET"
  264. default:
  265. prs[i].Name = sr.Replace(s)
  266. }
  267. ss := strings.Split(pr.Descr, "\n")
  268. for i := range ss {
  269. ss[i] = strings.TrimSpace(ss[i])
  270. }
  271. if len(ss) > 1 {
  272. prs[i].Descr = strings.Join(ss, " ")
  273. } else {
  274. prs[i].Descr = ss[0]
  275. }
  276. prs[i].Value, _ = strconv.Atoi(pr.Value)
  277. }
  278. return prs
  279. }
  280. func parseAddrFamilyNumbers(w io.Writer, r io.Reader) error {
  281. dec := xml.NewDecoder(r)
  282. var afn addrFamilylNumbers
  283. if err := dec.Decode(&afn); err != nil {
  284. return err
  285. }
  286. afrs := afn.escape()
  287. fmt.Fprintf(w, "// %s, Updated: %s\n", afn.Title, afn.Updated)
  288. fmt.Fprintf(w, "const (\n")
  289. for _, afr := range afrs {
  290. if afr.Name == "" {
  291. continue
  292. }
  293. fmt.Fprintf(w, "AddrFamily%s = %d", afr.Name, afr.Value)
  294. fmt.Fprintf(w, "// %s\n", afr.Descr)
  295. }
  296. fmt.Fprintf(w, ")\n")
  297. return nil
  298. }
  299. type addrFamilylNumbers struct {
  300. XMLName xml.Name `xml:"registry"`
  301. Title string `xml:"title"`
  302. Updated string `xml:"updated"`
  303. RegTitle string `xml:"registry>title"`
  304. Note string `xml:"registry>note"`
  305. Records []struct {
  306. Value string `xml:"value"`
  307. Descr string `xml:"description"`
  308. } `xml:"registry>record"`
  309. }
  310. type canonAddrFamilyRecord struct {
  311. Name string
  312. Descr string
  313. Value int
  314. }
  315. func (afn *addrFamilylNumbers) escape() []canonAddrFamilyRecord {
  316. afrs := make([]canonAddrFamilyRecord, len(afn.Records))
  317. sr := strings.NewReplacer(
  318. "IP version 4", "IPv4",
  319. "IP version 6", "IPv6",
  320. "Identifier", "ID",
  321. "-", "",
  322. "-", "",
  323. "/", "",
  324. ".", "",
  325. " ", "",
  326. )
  327. for i, afr := range afn.Records {
  328. if strings.Contains(afr.Descr, "Unassigned") ||
  329. strings.Contains(afr.Descr, "Reserved") {
  330. continue
  331. }
  332. afrs[i].Descr = afr.Descr
  333. s := strings.TrimSpace(afr.Descr)
  334. switch s {
  335. case "IP (IP version 4)":
  336. afrs[i].Name = "IPv4"
  337. case "IP6 (IP version 6)":
  338. afrs[i].Name = "IPv6"
  339. case "AFI for L2VPN information":
  340. afrs[i].Name = "L2VPN"
  341. case "E.164 with NSAP format subaddress":
  342. afrs[i].Name = "E164withSubaddress"
  343. case "MT IP: Multi-Topology IP version 4":
  344. afrs[i].Name = "MTIPv4"
  345. case "MAC/24":
  346. afrs[i].Name = "MACFinal24bits"
  347. case "MAC/40":
  348. afrs[i].Name = "MACFinal40bits"
  349. case "IPv6/64":
  350. afrs[i].Name = "IPv6Initial64bits"
  351. default:
  352. n := strings.Index(s, "(")
  353. if n > 0 {
  354. s = s[:n]
  355. }
  356. n = strings.Index(s, ":")
  357. if n > 0 {
  358. s = s[:n]
  359. }
  360. afrs[i].Name = sr.Replace(s)
  361. }
  362. afrs[i].Value, _ = strconv.Atoi(afr.Value)
  363. }
  364. return afrs
  365. }